React公式ドキュメントにある三目並べについてのメモ🔰(途中)

# 前提
HTML/CSSは仕事で使っておりJSは試行錯誤して触りながら動かしている程度の人間です。

まずJSをもっと勉強してからReactしろって話はおいておいて。
React.jsの公式ドキュメントにある三目並べをやっているのですが、理解できずに躓いた部分のメモです。まったくもって解説とかではなく、躓いた部分について振り返りながら「なるほど。こういうことか」と思っている頭の中を書き連ねており、学習して成長するためにも恥をさらしまくっているだけですのであしからず。しかも思考を書き連ねているので非常に読みづらいですが、自分の頭の中をまとめるものなのでご容赦を。

JSがわかる方にとっては小学生の頭の中を見ているみたいな感じだと思うので温かく見守っていただけると嬉しいです。そして間違っている点はコメントいただけたら泣いて喜びます。

# 疑問1：state のリフトアップ
https://ja.react.dev/learn/tutorial-tic-tac-toe#completing-the-game

「ゲームを完成させる」章のstate のリフトアップ以降から頭に入らない…。これ理解できなくてもReactがどういうものなのかを知るだけなら気にせず先に進んだほうがいいものなんでしょうけど、この段階から理解できなくてそれ以降の話にもついていけなくて頭の中がこんがりはじめたので復習も兼ねて。

ゲームの勝者を決めるためにどの枠が埋まっているのかを把握しなければならないという概要は理解できるのですが、以下の記述の意味が理解しきれない。（書いてたらなんとなくわかってきたので正確には「理解しきれなかった」）

```react
    const [squares, setSquares] = useState(Array(9).fill(null));
```

# 疑問1：解決
`[squares, setSquares]`でsquaresという名前の変数を宣言している。そのデフォルト値として`(Array(9).fill(null))`により9個の要素を持つ配列を作成し、それぞれの要素をnullとする。
ここまでは大丈夫。

> useState() コールは、state 変数 squares を宣言し、初期値をこの配列にします。

この`useState`ってなんだっけ？
答えは『インタラクティブなコンポーネントの作成』の章にあり。
> 何かを「記憶」するために、コンポーネントは state というものを使用します。
React は、useState という特別な関数を提供しており、コンポーネントからこれを呼び出すことで「記憶」を行わせることができます。Square の現在の値を state に保存し、Square がクリックされたときにその値を変更しましょう。

つまり**squaresという名前の変数に9個の要素を持つ配列を作成し、それぞれの要素をnull（初期値）を記憶させている**ということであっているのかな？

そして`[squares, setSquares]`は、`squares` が state の現在値を格納し、`setSquares` はその値を更新するために使う関数を指定している。
これ、`setSquares`で関数を指定する意味って何なんだろ？(以降の作業中に解決済)

まぁ取り合えずこれで

```react
    [null, null, null, null, null, null, null, null, null]
```
という配列が作られる。

# 疑問2：Square がクリックされたときに起こることを変更
```react
    function Square({ value, onSquareClick }) { //2
      return (
        <button className="square" onClick={onSquareClick}> //1
          {value}
        </button>
      );
    }
    
    export default function Board() {
      const [squares, setSquares] = useState(Array(9).fill(null));
    
      function handleClick() {
        const nextSquares = squares.slice();
        nextSquares[0] = "X";
        setSquares(nextSquares);
      } //4
    
      return (
        <>
          <div className="board-row">
            <Square value={squares[0]} onSquareClick={handleClick} /> //3
            //...
      );
    }
```
この1~4の一連の流れがわからない！

1\. buttonをクリックしたときに `onClick` で `Square` コンポーネントが `onSquareClick` という名前の関数を呼び出す。

2\. 1で指定した関数 `onSquareClick` を `Square` コンポーネントの props に追加する。

**この props に追加する作業って何…？**
propsがいまいちわかっていないのですよね。

* * *
**propsとは？**

https://ja.react.dev/learn/tutorial-tic-tac-toe#passing-data-through-props

ざっとpropsでできることはわかるものの、そもそもpropsって何なの？という疑問が解消されない。

https://qiita.com/rio_threehouse/items/7632f5a593cf218b9504

めちゃくちゃわかりやすい記事ありました！
> props : 親コンポーネントから子コンポーネントへ値を渡すための仕組み

* * *
つまり `function Square({ value, onSquareClick }) {` で子であるBoardの `onSquareClick` に関するデータを引き抜いてきている？
> 子から親へ値を渡すことはできない

とあるので親はBoard、子はSquareが正しいのか…？とか思ったのですが、**state のリフトアップ** の冒頭にこたえが書いてありました。記憶力大丈夫なのかしら？

> ゲームの state を各 Square ではなく親の Board コンポーネントに保持させることです。Board コンポーネントは、それぞれの Square に、何を表示するのか props を使って伝えることができます。

そもそも1つ1つの四角 `Sqare`のまとまりが `Board` なのでした。そんな初歩的なこと忘れる？こうやって疑問点や復習を書き出すとどれだけ理解せずに進めてるかわかっていいですね。

さて、もはや余談になってしまった項目2は解決したので3へ。

3\. 2で作った関数 `onSquareClick` を `onSquareClick={handleClick}` により接続

4\. 3で作った関数 `handleClick` に内容を定義する。その定義の内容は以下

```react
    function handleClick() {
        const nextSquares = squares.slice();
        nextSquares[0] = "X";
        setSquares(nextSquares);
      } 
```
`nextSquares` という名前の関数を作り、slice() 配列メソッドを使って squares 配列のコピー (nextSquares) を作成。

:slight_smile: ????????????????

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

あ、これnextSquaresはsquares配列のコピーを作りますって宣言してるのか。最初からそう言っているんだけど一瞬、何??????????????ってなってしまった。

で、`nextSquares[0]` は X と表示され、新しく作成された `nextSquares` 配列を使って、`setSquares` 関数を呼び出して状態を更新。これにより、`squares` の内容が新しい配列で置き換わる。

ここでやっと**stateのリフトアップ**で記述した `setSquares` ！ 

```react
    [null, null, null, null, null, null, null, null, null]
```
これを更新しているのか。

## 疑問2:解決
一連の流れをまとめると、四角（Square）をクリックしたら「X」が表示され、[null, null, null, null, null, null, null, null, null]が更新される。

こうやって読み解いていくと「説明通りのことしか起こっていないわ」と毎回思うんですが、それに気づくまでが長いんですよね。

そうして、これでは `nextSquares[0]` の四角しか「X」にならないので `nextSquares[i] = "X";`にしてと続いていく…

勝敗を決める部分は今からなので、また更新するかと思いますがいったんここまで。