デザイナーがTutorial: Intro To Reactを和訳しながらやってみたで( `・∀・´)ノ来年モヨロシク

f:id:gashoo:20171221033831p:plain

こちら、GASHOO Inc. Advent Calendar 2017の記事です。

Reactを学習することになった経緯💢

弊社代表「デザイナーもReact触れなアカンで!(σ・∀・)σゲッツ!!」

ぼく「はあ( ゚∀゚)」

この記事を書こうと思った理由🖊

  • モダンなフロントエンドの開発トレンドを知らねばならん
  • とりあえず入門で勧められたReact Tutorial、日本語版が見つからない。(同じ理由で挫折した人がいるはず)
  • 意外とやってみたら楽しい

というわけで、まともに触れませんが、挑戦していきながらReactの門を叩こうと思います。

謝罪🙇

Reduxは時間の都合で間に合わんかったんじゃ。。。

ぼくのJsレベル

  • jQueryは結構さわってた
  • 生のJsもちょくちょく書いてた(document.querySelector('hoge')ですねわかります)
  • ES6、ちょっとだけ分かる
  • 設計とかはさっぱり

実施環境

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.hatenablog.com

gashoo.hatenablog.com

gashoo.hatenablog.com

GASHOO Inc. Advent Calendar 2017

adventar.org