React入門４: リファクタリング [リフトアップ編]

# はじめに
私自身の復習兼、備忘録的な意味もあり、複数回の記事に渡って React を用いてマルバツゲーム(三目並べ)を開発していきたいと思います。
- [React](https://ja.react.dev/)
- [CodeSandbox(公式)](https://codesandbox.io/)
- [CodeSandbox(非公式)](https://csb-jp.github.io/)

## シリーズの一覧
1. [React入門１: 環境構築 [オンライン版]](https://qiita.com/banana_bancho/items/64fa6ccb58101eadbb63)
   - [React入門1.5: 環境構築 [ローカル版-番外編]](https://qiita.com/banana_bancho/private/30f5d9d2c5eea00ac11c)
1. [React入門２: 盤面の作成](https://qiita.com/banana_bancho/private/c50495b5d4c30555cec3)
1. [React入門３: インタラクションの実装](https://qiita.com/banana_bancho/private/557d14b2413cb0317ce4)
1. React入門４: リファクタリング [リフトアップ編] (今回)
1. [React入門５: リファクタリング [インタラクション編]](https://qiita.com/banana_bancho/private/3f20d23aadb49fe233f8)
1. [React入門６: 手番の実装](https://qiita.com/banana_bancho/private/6bed838f67e575f58b72)
1. [React入門７: ゲームの勝利判定](https://qiita.com/banana_bancho/private/c0eca4e9348edb430561)
1. [React入門８: テキストの実装](https://qiita.com/banana_bancho/private/b841b1ce38482b31753c)
1. [React入門９: タイムトラベル(1)](https://qiita.com/banana_bancho/private/c674872e32fcb52bb2a0)
1. [React入門10: タイムトラベル(2)](https://qiita.com/banana_bancho/private/861398f1fa4efd378938)
1. [React入門11: タイムトラベル(3)](https://qiita.com/banana_bancho/private/0d3cf7e1b1ebbf20c5e0)

# 目的について
## 全体の目的
React公式のチュートリアルで公開されているマルバツゲームを 3x3 のマスで実装していきます。

https://ja.react.dev/learn/tutorial-tic-tac-toe

## 今回の目的
ゲームの勝利判定をするために、全マスの状態を ```Board``` コンポーネントで把握できるように、プログラムを変更していきます。

# リファクタリング
リファクタリング(refactoring)とは次のことを意味します。
- プログラムに機能を追加すること
- ソースコードを管理しやすいものへと修正すること

次のページで、前回のソースファイルを確認できます。

https://codesandbox.io/p/sandbox/react-tutorial3-fqgyvp

- 前回の内容はコチラから！

https://qiita.com/banana_bancho/items/557d14b2413cb0317ce4

## マスの状態を管理するコンポーネント
ここで、現在のプログラムを振り返ってみます。
- ```Board``` コンポーネントと ```Square``` コンポーネントは親子関係にある ([第2回の記事を参照](https://qiita.com/banana_bancho/private/c50495b5d4c30555cec3#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E5%88%86%E8%A7%A3))
    - ```Board``` コンポーネントが9つの ```Square``` コンポーネントを呼び出している
- 9つのマスの状態は ```Square``` コンポーネントによってそれぞれ制御されている
    - マスの状態は ```state``` 型の ```value``` 変数が示す

勝利条件が成り立っているか否かを判定するには、盤面すなわち全てのマスの状態を取得する必要があります。そこで、マスの状態を ```Square``` コンポーネントから親の ```Board``` コンポーネントで管理ができるようにプログラムを変更していきます。このようなリファクタリングを**リフトアップ**といいます。

マスの状態をリフトアップするために、App.js に次の変更を加えましょう。
- ```Square``` コンポーネントの変更
    - ```state``` 型の ```value``` 変数を削除する
    - プロパティとして ```value``` を追加する
    - ```handleClick()``` 関数を削除する
    - ```<button>``` 要素の ```onClick``` プロパティを削除する
- ```Board``` コンポーネントの変更
    - ```state``` 型の ```squares``` 配列を宣言する
        - 配列の要素数は9個とし、各要素の初期値は ```null``` とする
        - ```setSquares``` という関数を呼び出すと ```squares``` 配列を更新できるようにする
    - 各 ```Square``` コンポーネントの ```value``` プロパティに ```squares``` 配列の要素を渡す
```jsx:App.js
import { useState } from "react";
import "./styles.css";

function Square({ value }) {
  return <button className="square">{value}</button>;
}

export default function Board() {
  const [squares, setSquares] = useState(Array(9).fill(null));

  return (
    <>
      <div className="board-row">
        <Square value={squares[0]} />
        <Square value={squares[1]} />
        <Square value={squares[2]} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} />
        <Square value={squares[4]} />
        <Square value={squares[5]} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} />
        <Square value={squares[7]} />
        <Square value={squares[8]} />
      </div>
    </>
  );
}
```

動作結果を次に示します。```Square``` コンポーネントの変更にて ```<button>``` 要素の ```onClick``` プロパティを削除したため、マスに対してマウスクリックをしても、「X」は表示されません。しかし、各 ```Square``` コンポーネントは、```value``` プロパティを通じて ```Board``` コンポーネントから ```squares``` 配列の要素を受け取っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/2c318f27-613c-6d60-0eb4-617f62f3b96b.png)

### リフトアップの事例
```state``` 型の変数について、リフトアップが行われる場面としては次が挙げられます。
1. 子コンポーネント同士で情報を共有させたいとき
1. 複数の子コンポーネントの情報を取得したいとき

各場面をオセロで例えてみました。

![リファクタリングの事例.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/e26387f6-84cf-0cd6-3d79-dd9f148d85f3.jpeg)

なお、マルバツゲームで行ったリフトアップは「複数の ```Square``` コンポーネントからマスの情報を取得したい」ため、2つ目の場面に該当します。このようなときには、親コンポーネントで ```state``` 型の変数もしくは配列を宣言して、子コンポーネントを呼び出すときにプロパティで情報を渡します。


# おわりに
今回は、マスの状態を ```Board``` コンポーネントで管理できるように変更しました。次のページに現段階のソースファイルを示します。

https://codesandbox.io/p/sandbox/react-tutorial4-vj36hl

次回は、今回のリファクタリングで失ってしまったマウスクリックのインタラクションを再実装していきます。 

https://qiita.com/banana_bancho/items/3f20d23aadb49fe233f8