Reactのチュートリアルをやってみた②

# はじめに
- Reactを使って画面作成をしてみたいと思うようになり、サイトを調べて[チュートリアル](https://ja.reactjs.org/tutorial/tutorial.html) を試しにやってみました。
- ここにかかれていることをサイト内にある[スターターコード](https://codepen.io/gaearon/pen/oWWQNa?editors=0010`) を使って試したものになります。
    - ○×ゲームを作ることが題材となっています。
- スターターコードにチュートリアルの内容に従いコードを書いていくことで動きを確認することはできました。
- [Reactのチュートリアルをやってみた①](https://qiita.com/nogoo/items/4d7db00df4a374e4cd2d) に投稿させていただいた第2弾になります。
    - 前回は、`Props`と`state`について、理解した内容をイメージにしてみました。
- 今回は、ゲーム完成までのコーディングを行うまでに学んだ以下の内容について纏めてみたいと思います。
    - State のリフトアップ（親：Boardが子：Squareをコントロールできるようにする）
    - 関数コンポーネント
    - 番手の処理
    - 勝ち負けの判定

# 前回のおさらい
- `Props`は、子のコンポーネントに対して引数を受け渡すのに利用される
- `state`は、自コンポーネント内で情報を保持し記憶しておくことができる
- 前回は、SquareとBoardのコンポーネントを準備し、Squareでイベントを検知して、情報を記憶しておき、Boardを再描画することで、Squareで記憶した値を表示できることを理解しました。イメージにするとこんな感じだと理解しました。
　　　　　　　　<img width="75%" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/14a85d61-18ea-8085-2933-fb0b1309ed03.png">

# 今回理解したこと
### Stateのリフトアップ ###
今、行っているチュートリアルでは○×ゲームを完成させることにありますので、`Square`コンポーネントで記憶している内容を`Board`コンポーネントで収集し、盤面の内容から勝ち負けを判定できるようにする必要があります。
そのため、以下のイメージにあるようなことをできるようにする必要があります。
　　　　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/7cc93a4a-d296-cd92-954e-554d09895a65.png)

そのためには、以下のイメージのように、親のコンポーネントで`state`を宣言して、`Props`を使って子のコンポーネントに情報を展開することで、親コンポーネントで情報を管理し、子コンポーネント間も親を通して情報のやり取りをできるようにすることでStateのリフトアップを行います。
　　　　　　　　<img width="50%" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/06da4139-777d-271a-b728-54a26431a125.png">

チュートリアルの○×ゲームでは、クリックのイベントも親コンポーネントで定義し、子コンポーネントの振る舞いを決めます。子コンポーネントは、クリックイベントが発生したら親コンポーネントが定義したイベントに従うようにしています。
コンポーネントのイメージと処理の流れをイメージしてみると、このような感じになると理解しました。
　　　　　<img width="75% alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/ee5ef76a-b46c-b4d2-41c8-1f492b4e7325.png">



### 関数コンポーネント ###
Reactでは、`rendaer`メソッドだけを有して、`state`を持たないコンポーネントは、`React.component`を継承する代わりに、`Props`を引数として受け取り、表示すべき内容だけを返す（return）できるように関数としてていぎすることができる。
クラスコンポーネントとして書くより、関数コンポーネントはコーディングが楽になる。
実際、stateのリフトアップした結果を見てみると、実際にやっていることは、`render`メソッドだけになっています。
　　　　　<img width="50%" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/9554ffca-cc5d-ad99-0ef0-bd60b946c8ba.png">


### 番手の処理 ###
番手の処理、つまり”○” と ”×” の攻め手の切り替えが👆の処理までだと実現できていないので、実現しましょう！という話になります。
ここは、`state`で真偽（True/False）を記憶して、その評価の結果によって、”○”と”×”を切り替えられるようにしていくことで実現できます。
- `Board`コンポーネントの`state`に変数：`xIsNext`を`true`を初期地として追加
- イベントが発生するたびに真偽の変更と、"○"と"×"の切り替えができるように`handleClick`関数に処理を追加
    - squares[i]に変数：`xIsNext`の真偽によって、"○" か"×"をセット
    - setStateメソッドで、`squares[i]`を`state.squares`に、変数：`xIsNext`に変数：`xIsNext`ではない値を`state`の情報として記憶する
- `Board`コンポーネントのレンダー内に`const`で定義されている今、どっちの番かを表示する`status`にも変数：`xIsNext`の真偽によって、"○" か"×"を切り替えができるように書き換える

### 勝ち負けの判定 ###
勝ち負けの判定をするためのcomponentなどの描画などが目的の関数コンポートンとは異なるヘルパー関数を用意するとあった。
ここでは、処理のイメージ化して書いてきたけど、純粋にロジックなのでコードベースで理解をした。
コードは以下のように`function`で関数であることを宣言して、関数名(引数)として`return`で処理結果を返している。

``` react
function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

```
一方の呼び出し側の`Board`コンポートでは、以下のように書き換えることで、勝ち負けの判定の結果に基づき、`const`で定義していた`status`を`let`（再代入可能な変数に定義しなおしている）の`status`に対して、ゲームが続行で、手番がどっちか、もしくは決着がついて、Winnerが誰になったのか、文字列を再代入する形で表現できるようにしている。

``` react
  render() {
    const winner = calculateWinner(this.state.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }
```

### まとめ ###
準備するコンポーネントが 'state' を定義し情報を記憶させておくべきコンポーネントか否かでコンポーネントクラスで定義するのか、関数コンポーネントとして定義するのかを整理しながら、まずは動かすためにコンポーネントクラスで定義したとしても、やりたいことを整理していく中で **リファクタリング** しながら実装することが<font color="Red">**ポイント**</font>になると理解した。