これは何
- 「デザイナーもReact書いてくださいよ」って空気になったときに読むと役立つかもしれない記事です
- 基本的に筆者が学んだ流れを記載しています
- そのため、世間一般のベストプラクティスではないと思います
- エンジニアの方から見ると邪道な流れ・説明の仕方かもしれませんが、デザイナーに教える上での分かりやすさを重視していますのでご了承ください
-
この記事の中で使っているコードはこちらのリポジトリで公開しています
- コミットを辿ってもらえれば、各セクションの内容が全て見れます
- ※言い訳がましいですが、筆者もReactに精通している程ではなく「デザイナーにしては割と知ってる」レベルです
- もし説明に間違いや不足があれば編集リクエストをお願いします
対象読者
- Web or UIデザイナー
- HTMLとCSSは普通に書けるけど、Reactはほぼ全く触ったことがない人
- 1人で完全に実装したいってほどではないけど、簡単な部分は書けるようになりたいと思っている人
- メイン対象はデザイナーなものの、初心者向けの内容ではあるので「新人プログラマ」も対象になるかもしれません
筆者はどんな人
普段の業務ではUIのモックアップを作って、ある程度はReactでのコーディングもしています。
また、業務レベルではありませんが自分のポートフォリオサイトは全てReactで書いています。
Reactの概念について
概念を説明するといっても、深い部分までは扱いません。
あくまでデザイナー向け、かつ、不慣れな人でもパンクしない程度の内容にとどめます。
上記の関係で「Reactに限らない説明」も多いです。
コンポーネントを組み合わせてインターフェースを作成できる
- ボタン・タブ・リスト……UIの種別を問わず、一度定義すればそれを繰り返し使える
- 同じものを何回も作らなくて良い
- FigmaやSketchなどのツールを用いてインターフェースを作るときの考え方と非常に似ている1
- 慣れれば、UIツール上でコンポーネントを作っている最中に、コードでのコンポーネントの実装方法も想像できる
色々な場所が変化するインターフェースを作成しやすい
- HTMLやCSSだけでサイトを作るのはかなり大変
- 「ログインしていたら」とか「商品を買い物かごに入れていたら」といった、任意の条件にあわせたインターフェースの変化は上手く表現できない
- HTMLだけだったら「登録されているユーザー情報を100人分表示する」場面では100回繰り返して書く必要がある
- それ以外にも色々……
- Reactなら上記の「条件の違い」や「繰り返し」も表現できる2
- HTMLやCSSだけではできないことができるようになる
- 効率の良いコードを書けるようになる
Reactを触っていく順番
公式のチュートリアルとは全然違う順番ですが、デザイナーならこういう順番で触れるのが良いのではないでしょうか。
私がいつも伝える上で大事にしているのは「何も分からない……」と諦めの感情を抱かせないようにすることです。
「完全に理解した」と調子に乗るのも良くありませんが「意外と理解できる、楽しいぞ!」と思えるのが重要だと思います。
HTMLもどきとCSSもどきだけを触れるようになる
デザイナーもReactを触ると言っても、最初のうちはHTMLもどきとCSSもどきを触れるようになるだけでも十分かと思います。
簡単なスタイル調整や文言の修正をエンジニアから巻き取れるだけでも、チームの作業スピードは上がるんじゃないでしょうか。
それにしてももどき
ってなんだよって話ですよね。
細かい説明をしだすと難しくなるので、実際のコードを見てください。
Create React Appというスターターキットのようなものがあり、そこで生成されるコードをアレンジして例に出します。
import logo from './logo.svg';
import './App.css';
const firstName = "John"
const lastName = "Doe"
const fullName = `${firstName} ${lastName}`
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Hello, {fullName}
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
見た目はこんな感じです。
App.js
においてimport
やconst
やfunction
やexport
は見慣れないかもしれません。
しかしreturn
以降は見覚えがありますよね?
そう、ほぼHTMLなんです。
現段階で微妙にHTMLと違うのは以下の2点のみ。
-
class
ではなくclassName
と書かれている -
img
タグのsrc
や、p
タグの中で{}
を使って書かれている箇所がある({logo}
と{userName}
)
classNameについて
Reactの世界ではclass
という単語はCSS以外の場所で使われています。
そのためCSSのクラス名
を指定する際には、class
ではなくclassName
と書く必要があります
若干違和感を覚えるかもしれませんが、これは暗記するしかありません。
ちなみに似た話でlabel
とinput
を紐付ける際に、HTMLではfor
を使いますが、ReactではhtmlFor
を使います。
こちらも違和感はあると思いますが「Reactではそうやって書くんだな」と割り切って覚えていただきたいです。
ここで「冒頭で出ていた『CSSもどき』ってclass
がclassName
に変わるだけってこと?」と思われる方もいるかもしれません。
半分正解で、半分不正解です。
Reactにおいてスタイリングを施す方法はかなりたくさんあるため、一概には言えないのです。
例えば「font-sizeが20pxで赤色の文字」をスタイリングするだけでも、次のような方法があります。
例1 インラインスタイル
// インラインスタイル
function Example1() {
return (
<p style={{ fontSize: 20, color: "#f00" }}>スタイリングの例</p>
)
}
例2 普通のCSSやSassを使う
// React側のコード
import './style.css'
function Example2() {
return (
<p className="foo">スタイリングの例</p>
)
}
/* CSS側のコード */
.foo {
font-size: 20px;
color: #f00;
}
例3 CSS Modulesを使う
// React側のコード
import styles from './style.css'
function Example3() {
return (
<p className={styles.foo}>スタイリングの例</p>
)
}
/* CSS側のコード */
.foo {
font-size: 20px;
color: #f00;
}
例4 CSS in JSを使う(ここではEmotion)
import { css } from "@emotion/react"
function Example4() {
return (
<p css={foo}>スタイリングの例</p>
)
}
const foo = css({
fontSize: 20,
color: "#f00"
})
たくさん例を出しましたがビビらせたい訳ではありません。
この例以外にもまだまだ色々な書き方があり、網羅的に説明するのが難しいことをお伝えしたいだけです。
更に言えば例1~4を見て頂ければ分かるとおり、それぞれ微妙に書き方は違うものの「ほぼCSS」ですよね?
そのため、使っているものさえ分かれば後は慣れるだけです。
「ウチってスタイリングには何を使ってるんですか?」と聞けば、エンジニアのみなさんが教えてくれることでしょう。
{}
の使用について
HTMLを書いていて、{}
が何かの役割を担うことはありませんよね?
ですが、Reactにおいては大活躍します。
HTMLもどきの中で{}
が出てきたら「このカッコの中ではJavaScriptが動いているんだな」と捉えてください。
img
タグでは
<img src={logo} className="App-logo" alt="logo" />
と書いてありますが、先ほどのコードの1行目には
import logo from './logo.svg';
と書いてあります。
これらを踏まえてimg
タグに書いてある内容をHTMLに翻訳(?)すると以下のようになります。
<img src='./logo.svg' className="App-logo" alt="logo" />
'./logo.svg'
の場所にあるファイルを{logo}
という書式で呼び出せるようになっているんですね。
また、コードの最初の方には以下の記述があります。
const firstName = "John"
const lastName = "Doe"
const fullName = `${firstName} ${lastName}`
こちらを日本語訳するとこんな感じです。
Johnという文字列をfirstNameという定数に突っ込みます
Doeという文字列をlastNameという定数に突っ込みます
firstNameとlastNameを合体させた文字列をfullNameという定数に突っ込みます
そしてfullName
は実際にはこのように使われています。
<p>
Hello, {fullName}
</p>
コードではこう書かれていますが、スクリーンショットを見るとHello, John Doe
と表示されています。
{}
で囲われたfullName
がJavaScriptとして動き、firstName
とlastName
の合体したもの、つまりJohn Doe
としてHTMLに表れているのです。
ここまでのまとめ
- デザイナーがReactを触り始めるなら、まずはHTMLもどきとCSSもどきを触れれば十分
- HTMLもどきは
className
だけは暗記しておきましょう - CSSもどきは色々な種類があるから身近にいるエンジニアに聞きましょう
-
{}
が出てきたら、今はひとまず「このカッコの中ではJavaScriptが動いているんだな」と理解できれば大丈夫
コンポーネントを使えるようになる
HTMLもどきとCSSもどきはだいたい触れるようになったとします。
お次は、最初の方で出したメリットの「コンポーネントを組み合わせてインターフェースを作成できる」を享受できるようになりましょう。
とりあえず作ってみる
まずは、新しくSomeComponent
という名前のコンポーネントを作ってみます。
function SomeComponent() {
return (
<p style={{ fontSize: 20, color: '#61dafb' }}>This is example component</p>
)
}
export default SomeComponent
export default SomeComponent
と書いてあるのは「よそのファイルでもSomeComponent
を使えるようにします!」って言ってるような雰囲気で捉えてください。
そのため、これを書き忘れると他のファイルで使い回せなくなってしまいます。
例なのでそう大したことはしていませんが、フォントサイズと色とテキストを定義したコンポーネントです。
これらの組み合わせはしょっちゅう使い回す場合、毎回同じHTMLとCSSを書くのは手間ですが、Reactなら1回ここで定義すれば後は何度でも使い回せます。
先ほど例で使っていたコードを少し改変して、SomeComponent
を利用してみましょう。
import logo from './logo.svg';
import './App.css';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import SomeComponent from './SomeComponent'
const firstName = "John"
const lastName = "Doe"
const fullName = `${firstName} ${lastName}`
function App() {
return (
<Router>
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Hello, {fullName}
</p>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
<ul className="linkList">
<li className="linkItem">
<Link to="/" className="link">Home</Link>
</li>
<li className="linkItem">
<Link to="/about" className="link">About</Link>
</li>
<li className="linkItem">
<Link to="/users" className="link">Users</Link>
</li>
</ul>
</header>
</div>
</Router>
);
}
function Home() {
return <h2>Home</h2>;
}
function About() {
return (
<>
<h2>About</h2>
<SomeComponent />
</>
);
}
function Users() {
return (
<>
<h2>Users</h2>
<SomeComponent />
</>
);
}
export default App;
※途中でSwitch
とかRoute
とか出てきていますが、無視して大丈夫です。
Home | About | Users |
---|---|---|
ページが3つあり、/home
、/about
、/users
だとします。
そして/about
、/users
では20pxで#61dafbの色のThis is example componentという文字列
、つまりSomeComponent
を使い回したいとします。
App.js
の最初の方で、SomeComponent
を呼び出していますね
import SomeComponent from './SomeComponent'
そして後の方で、繰り返し使っています。
function About() {
return (
<>
<h2>About</h2>
<SomeComponent />
</>
);
}
function Users() {
return (
<>
<h2>Users</h2>
<SomeComponent />
</>
);
}
これにより、/about
、/users
では見出しの下に同じサイズと色のテキストを呼び出すことができました。
オーバーライドできるようにする
FigmaやSketchでは、ボタンやタブやリストなど、よく使い回すものはコンポーネント(or シンボル)として定義して適宜オーバーライドしながら使っていますよね。
もちろんReactでも可能です。
先ほど作ったSomeComponentのテキストをオーバーライドできるようにしてみましょう。
- function SomeComponent() {
+ function SomeComponent({ text }) {
return (
- <p style={{ fontSize: 20, color: '#61dafb' }}>This is example component</p>
+ <p style={{ fontSize: 20, color: '#61dafb' }}>This is {text} component</p>
)
}
export default SomeComponent
まず、先ほどまではfunction SomeComponent()
だったのがfunction SomeComponent({ text })
と変わっています。
これは「text
って名前のデータを受け取ってきて使います」というニュアンスです。
そしてp
タグの中のテキストがThis is example component
からThis is {text} component
に変わっていますね。
これは「さっき受け取ってきたtext
の中身をここに表示します!」という感じです。
コンポーネントを更新できたら、App.js
も更新します。
function About() {
return (
<>
<h2>About</h2>
- <SomeComponent />
+ <SomeComponent text="about" />
</>
);
}
function Users() {
return (
<>
<h2>Users</h2>
- <SomeComponent />
+ <SomeComponent text="users" />
</>
);
}
2つのSomeComponent
の中で、それぞれ違うテキストを渡しています。
すると表示は以下のようになります。(見づらいので拡大してご覧ください )
About | Users |
---|---|
about
の文字を渡した方はThis is about component
に、
users
の文字を渡した方はThis is users component
になっているのがお分かりでしょうか?
もちろん文字以外にも色やサイズやレイアウトなど、色々なオーバーライドができます。
FigmaやSketchでできるオーバーライドはReactならなんでもできるので、興味を持ったら是非色々調べてみてください。
ここまでのまとめ
- 新規にファイルを作って「他のファイルでも使えるようにします」と宣言すればいつでも使い回せる
- 日頃FigmaやSketchで行っているようなオーバーライドもコードで実現できる
? :
とか&&
とかの書き方を理解してマークアップ・スタイリングができる
このくらいの時期になるとエンジニアが書いたコードを見て、謎の記号の組み合わせをたくさん発見するのではないでしょうか?
? :
&&
||
何が書いてあるかも良く分からないし、ググろうにもなんてググったら良いか分からないのではないでしょうか。
実はちゃんと名前があります。
-
? :
→ 三項演算子 -
&&
||
→ ショートサーキット評価(短絡評価)
難しく見えますが、ちょっとしたスタイリングの出し分けや要素の出し分けを検証するときに、デザイナーもこれが理解できていると非常に便利です。
よくある使い方を記載します。
? :
よくあるコードは、だいたいこんな感じです。
checked
は、どこかで別に宣言されていて「チェックされているか否か」を判断する役割のものだと思ってください。
checked ? <OkIcon /> : <NgIcon />
これを日本語訳すると「チェックされてたらOkIcon
コンポーネントを、されてなかったらNgIcon
コンポーネントを表示する」といった具合です。
一般化するとA ? B : C
は、AがあればBを、なければCを出す
です。
&&
よくあるコードは、だいたいこんな感じです。
error
はどこかで別に宣言されていて「エラーが発生しているか否か」を判断する役割のものだと思ってください。
error && <ErrorMessage />
これを日本語訳すると「エラーがあるときだけErrorMessage
を表示する」といった具合です。
一般化するとA && B
は、AがあればBを出す、Aがなければ何もしない
です。
||
よくあるコードは、だいたいこんな感じです。
currentValue
はどこかで別に宣言されていて「現在の値」が入っていると思ってください。
currentValue || 10
これを日本語訳すると「currentValue
があればそれを、なければ10を表示する」といった具合です。
一般化するとA || B
は、AがあればAを出す、AがなければBを出す
です。
ここで紹介した記号の書き方を駆使して自分だけでコードを書くのは難しいかもしれません。
ですが、現状の条件分岐が分かるだけでも、HTMLもどきやCSSもどきの編集によって進められるタスクは結構あるはずです。
また、foo && bar < 10 && baz === 'yes' && <Component />
のように複雑になっている場合もありますが、焦らず1つずつ読み解いていきましょう。
ここまでのまとめ
- 謎に見える記号の集まりも、ちゃんと名前もルールもある
- 若干アバウトな説明になるものの
-
A ? B : C
は、AがあればBを、なければCを出す
-
A && B
は、AがあればBを出す、Aがなければ何もしない
-
A || B
は、AがあればAを出す、AがなければBを出す
-
ダミーのStateを作って条件にあわせたマークアップ・スタイリングができる
最後です。これは結構難しく感じるかもしれませんがとても有用だと思います。
「条件をクリアしているときはAの見た目、そうでないときはBの見た目のボタンを作りたい」のようなことを考えるシーン、ありますよね?
完全な条件を実装するのは無理でも、手元でおおよその動きを検討してエンジニアに引き継ぐことはできます。
また先ほどのコードを改造して例に出します。
import logo from './logo.svg';
import './App.css';
import { useState } from 'react'
import AnotherComponent from './AnotherComponent'
const firstName = "John"
const lastName = "Doe"
const fullName = `${firstName} ${lastName}`
function App() {
const [status, setStatus] = useState(true)
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Hello, {fullName}
</p>
<AnotherComponent status={status} onClick={() => setStatus(!status)} />
</header>
</div>
);
}
export default App;
コンポーネントを扱う話で出したのと同様に、AnotherComponent
をimportしています。
import AnotherComponent from './AnotherComponent'
その後、return
の中でAnotherComponent
を使用しているのですが、なんだか難しい雰囲気になっていますね。
<AnotherComponent status={status} onClick={() => setStatus(!status)} />
このあたりの仕組みを解説します。
じつはAnotherComponent
を呼び出すより上で、useState
というものを呼び出しています。
import { useState } from 'react'
これが何かを最初から理解しようとすると混乱のもとなので、今は「そういうものがあるのか」ぐらいで大丈夫です。
そしてfunction App()
のすぐ下で、これまた初めて見る書き方のものがあります。
const [status, setStatus] = useState(true)
これも最初は書き方を真似ればOKです。
今は[foo, setFoo] = useState(初期値)
という書式だけ覚えてください。
どんな名前をつけても良いですが、foo
とつけたならsetFoo
だしbar
と名付けたならsetBar
にするのが1つ。
useState
の初期値はなんでもありですがデザイナーの範疇だとtrue
かfalse
かを入れておけば事足りる場合が多いです。
条件にあわせて変わるスタイルを組む、差し当たって、最初は条件をクリアしているのかいないのか、ぐらいの考え方でOKです。
デフォルトで条件をクリアしているようなものだったらtrue
を、デフォルトではクリアしていなさそうだったらfalse
を与えてあげてください。
そして話が若干前後しますがAnotherComponent
においては
<AnotherComponent status={status} onClick={() => setStatus(!status)} />
日本語訳すると「さっき定義したstatus
のデータを渡す。クリックした場合はstatus
のtrue
とfalse
を入れ替える」ようなイメージです。
じゃあAnotherComponent
自体のコードはどうなっているのかというと、以下です。
import './App.css';
function AnotherComponent({ status, onClick }) {
return (
<button
className={`button ${status ? 'button--ok' : 'button--ng'}`}
onClick={onClick}
>
Status is {status ? 'OK' : 'NG'}
</button>
)
}
export default AnotherComponent
ひとつずつ解説すると
function AnotherComponent({ status, onClick })
「status
とonClick
というデータを受け取ります」と宣言していて
<button
className={`button ${status ? 'button--ok' : 'button--ng'}`}
onClick={onClick}
>
「クラス名は、いつでもbutton
がついている。さっき受け取ったstatus
がtrue
だったらbutton--ok
というクラス名を、false
だったらbutton--ng
というクラス名をつける」
「ボタンをクリックしたときは、さっき受け取ったonClick
が発動する。つまり、クリックしたときにstatus
のtrue
とfalse
を入れ替える動きをする。」
これらが全部あわさると、クリックするたびボタンのラベルと色が変わる実装ができます。
条件にあわせたクラスの付け替えやアニメーション実装などができたら、エンジニアに引き継いで「実際の条件分岐」を適用してもらいましょう。
デザイナーは、スタイリングは得意だけど条件をつけたりするのが苦手。
エンジニアは、条件をつけるのは余裕だけどスタイリングは苦手。
という傾向があります。
そこを、仮の条件分岐でもデザイナーがスタイリングすることで、連携がしやすくなるはずです。
ここまでのまとめ
-
useState
というものを使うと、コードは少なめでも色々な状態を実現できる - 実際のプロダクトに即していなくても、UIの状態変化を手元で再現することができる
- デザイナーだけで完成させるための手立てというよりはエンジニアと上手く協力するための知識
まとめ
- HTMLとCSSだけじゃできないことも、Reactならできる
- ほとんどHTMLとCSSの知識で書ける箇所もある
- プラスαで覚えられれば、コードを読むときの迷いが減ったり、エンジニアとの連携がしやすくなる