デザイナーがTutorial: Intro To Reactを和訳しながらやってみたで( `・∀・´)ノ来年モヨロシク
こちら、GASHOO Inc. Advent Calendar 2017の記事です。
Reactを学習することになった経緯💢
弊社代表「デザイナーもReact触れなアカンで!(σ・∀・)σゲッツ!!」
ぼく「はあ( ゚∀゚)」
この記事を書こうと思った理由🖊
- モダンなフロントエンドの開発トレンドを知らねばならん
- とりあえず入門で勧められたReact Tutorial、日本語版が見つからない。(同じ理由で挫折した人がいるはず)
- 意外とやってみたら楽しい
というわけで、まともに触れませんが、挑戦していきながらReactの門を叩こうと思います。
謝罪🙇
Reduxは時間の都合で間に合わんかったんじゃ。。。
ぼくのJsレベル
実施環境
Mac OS X El Capitan (10.11.5)
Node.js V7.0.0
npm 3.10.8
ローカルマシン内にcreate-react-appをインストールし、 localhost:3000 で進捗を確認していきます。
和訳だけ見たいねん💢 という方
インストール&下準備
$ npm install -g create-react-app $ create-react-app my-app //my-appっていう名前でReactアプリケーションを作成 $ cd my-app $ rm -f src/* $ touch src/index.css src/index.js // src以下にindex.cssとindex.jsをつくる
以下、章に対応して考えていたことをまとめていきます。
最初の状態
GameがBoardをrenderして、BoardがSquareをrenderしているので、
なんとなく、Game > Board > Squareなのね、という解釈です。
Propsを通じてデータを渡す
突然 props とかstate とか出てくるけど違いが分からんので調べます。
Stateは「Componentが持っている状態」の事を、
Propsは「 親Componentから渡された値」を指します。
こちらを参考にしました
https://qiita.com/ryo_t/items/d1f080f77bdeff4fa2f4
状態を引き上げる
この章ではここが重要っぽい。
複数の子からのデータを集約する場合や、2つの子コンポーネントが互いに通信する場合は、親コンポーネントに存在するように状態を上位に移動します。 親は、親コンポーネントを介して子に状態を戻すことができるので、子コンポーネントは常に互いに、親と同期します。
で、component間はprivateとなってSquareコンポーネントから、Boardコンポーネントへアクセスすることができないので、■をクリックしたときの関数をSquare側へ渡そう、というみたいです。
親であるBoardクラスから状態が飛んでくる予定なので、
- Squareの render で this.state.value を this.props.value に置き換えます
- Squareの render で This.setState() を this.props.value に置き換えます
- 状態を持たないのでSquareからコンストラクタ定義を削除してください
こうなるようです。
そして以下の行、
四角をクリックしてみてください。handleClickをまだ定義していないので、エラーが発生します。これをBoardクラスに追加します。
ここで、
handleClick(i) { const squares = this.state.squares.slice(); squares[i] = 'X'; this.setState({squares: squares}); }
おお、なんじゃこれとなります。
this.state.squaresの配列をコピーして、squaresという新しい変数に代入。これをBoardコンポーネントのコンストラクタにいる this.state = { squares: ~~ }にセットするっぽいです。ややこしい。
Functional Components
この時点でSquareコンポーネントはコンストラクタ関数も内部的な処理も持っていないので、renderを返すだけの関数でOKよね、って話みたいです。
ターンを作る
そんなにつまづかなかったので割愛
勝者の定義
calculateWinner関数が一瞬「?」となるが、ようするに勝ちパターンである[0, 1, 2], [3, 4, 5]に一致するかを判定してるっぽいです。
ここまでで一応完成。次はターンを行き来する機能を作っていきます。
履歴の保存
上位のレベルのGameコンポーネントが移動リストの表示を担当するようにします。(強制)
Boardコンポーネントに書いていた内容をGameコンポーネントにお引っ越し。同じようにコンストラクタを定義して、下記のタスクを終わらせます。
- Boardでコンストラクタを削除します
- Boradの renderSquare で this.state.squares[i] を this.props.squares[i] に置き換えます
- Boardの renderSquare で this.handleClick(i) を this.props.onClick(i) に置き換えます
これで、Gameコンポーネント → Boardコンポーネント → Square関数という風になります。
で、handleClickメソッドをGameコンポーネントに移すときには、historyという状態にconcatを使ってどこどこゲームの状態のオブジェクトが入っていく感じですね。はじめの
このようなオブジェクトを状態に格納するとしましょう
history = [ { squares: [ null, null, null, null, null, null, null, null, null, ] }, { squares: [ null, null, null, null, 'X', null, null, null, null, ] }, // ... ]
こんな感じで入っていくわけですね。
Keys
keyというプロパティが、Reactが内部で色々するために勝手にできるので、適切なkeyを設定しましょうね、ってことらしい。適切なkeyってのは、重複しないユニークな値を設定してねってことらしいです。
紆余曲折あって完成
言われるがままコードを書いていたが、とりあえず完成。
とりあえず、このチュートリアルで理解できたことは、
- 親と子の関係を持つコンポーネントという単位で構成していく
- propsは親から子へ値を渡す時、stateはコンポーネントの状態を表す
- 子から親へはアクセスできないので、親 → 子へのデータ渡しの形を基本にする
本当に基本的なことしか理解していないので、来年はもっと環境周りを含め、色々理解していきたいですね。
アドベントカレンダー、初めて書いてみた感想
- いつもぼんやり考えていることを、人に伝わるように書くのは難しい
- 定期的に続けることが一番難しい
- たった4回の更新だけど、すっぽかさずにできたから良かった
- 文体がCVRに影響するのか個人的に観察してたけど、あんまりないっぽい。大事なのは見出しと画像 (ちなみに、絵文字の多用はCVRに関係はなく、趣味である)
- はてなブログ、もうちょいアクセス解析ガッツリしたい感
- markdown記法がノールックで結構書けるようになった
- Gashooのアピールになったのだろうか、来年はもうちょい統一感のあるテーマで書きたい
- デザイナーなのに、デザインについて書いたのは1回だけ(いいよね)
- 自分は文章を書くのはあまり嫌いではないようだ
そんな感じで、白石の2017年アドベントカレンダー、お先に終了とさせていただきます!ありがとうございました。🙇
Gashooのアドベントカレンダーはまだまだ続くので、お楽しみください。🙇🙇🙇
余談
過去の白石の2017アドベントカレンダー
GASHOO Inc. Advent Calendar 2017