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入門３: インタラクションの実装 (今回)
1. [React入門４: リファクタリング [リフトアップ編]](https://qiita.com/banana_bancho/private/81730326c004e52c6aad)
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

## 今回の目的
盤面上にあるマスをマウスクリックすると「X」が表示されるようにしていきます。

# インタラクションの実装
次のページで、前回のソースファイルを確認できます。

https://codesandbox.io/p/sandbox/react-tutorial2-y2wlsd

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

https://qiita.com/banana_bancho/items/c50495b5d4c30555cec3

## イベントの設定
```Square``` コンポーネントを次のように書き換えましょう。
- コンポーネント内に ```handleClick()``` 関数を実装する
    - 仮引数はなし
    - コンソールにクリックされた旨を出力させる
- ```<button>``` 要素に ```onClick``` プロパティを追加して、 ```handleClick``` 関数を指定する

```JSX: Square()コンポーネント
function Square({ value }) {
  function handleClick() {
    console.log("clicked!");
  }

  return (
    <button className="square" onClick={handleClick}>
      {value}
    </button>
  );
}
```

コンソールを表示させて( [表示方法: [画面の内容 > プレビュー > (A)] 参照](https://qiita.com/banana_bancho/items/64fa6ccb58101eadbb63#%E7%94%BB%E9%9D%A2%E3%81%AE%E5%86%85%E5%AE%B9) )、実行結果を確認しましょう。いずれかのマスをクリックするとコンソール上に「clicked!」と表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/d6f2c534-fafd-be17-c373-ce8944f2acb7.png)

## 情報の記憶
```Square``` コンポーネントに、クリックされたことを記憶して「X」マークを表示するようにしていきます。そこで、React が提供している [```state``` コンポーネント](https://react.dev/learn/state-a-components-memory)と [```useState()``` 関数](https://react.dev/reference/react/useState)を実装していきます。

### ```state``` コンポーネントと ```useState()``` 関数
それぞれ、React 独自の概念で少し難しいので、ここでは ```state``` という変数の型があり、```useState()``` 関数で ```state``` 型の変数を宣言できるとイメージしてください。次のページから、```state``` の挙動が一般的な JavaScript の変数と異なることを確認できます。

https://ja.react.dev/learn/state-as-a-snapshot


```state``` 型の変数の初期化は次のような構文となります。まず、```useState``` 関数を利用するには、ファイルインポートが必要です。宣言について、```set関数``` は、```変数名``` の値を変更する際に呼び出す関数のことです。これは「 ```set + 変数名(頭文字は大文字)``` 」と名付けれられることが多いです。**set 関数を実行すると、そのコンポーネントは再レンダーされます**([第5回の記事](https://qiita.com/banana_bancho/private/3f20d23aadb49fe233f8) に関わる内容でかなり重要です)。
```JSX:
import { useState } from 'react';

// state型変数の宣言
const [変数名, set 関数] = useState(初期値);

// state型変数の値更新
set 関数(値)
```

では、App.js に次の変更を加えましょう。
-  React から ```useState``` 関数をインポートする
-  ```Square``` コンポーネントの変更
    -  ```value``` プロパティを削除する
    -  ```state``` 型の ```value``` 変数を宣言する
        -  初期値は ```null``` とする
        -  ```setValue``` という関数を呼び出すと ```value``` 変数の値を更新できるようにする
    -  クリックされると ```value``` 変数の値が ```'X'``` に更新される
        - コンソールへ出力する処理は削除する
- ```Board``` コンポーネントの変更
    - 全ての ```Square``` コンポーネントから ```value``` プロパティを削除する

```jsx: App.js
import { useState } from "react";
import "./styles.css";

function Square() {
  const [value, setValue] = useState(null);

  function handleClick() {
    setValue("X");
  }

  return (
    <button className="square" onClick={handleClick}>
      {value}
    </button>
  );
}

export default function Board() {
  return (
    <>
      <div className="board-row">
        <Square />
        <Square />
        <Square />
      </div>
      <div className="board-row">
        <Square />
        <Square />
        <Square />
      </div>
      <div className="board-row">
        <Square />
        <Square />
        <Square />
      </div>
    </>
  );
}
```

動作結果の動画を次に示します。これで、空白のマスをクリックすると「X」が表示されるようになりました。

![状態の記憶.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/d1ebc116-b97a-a578-acc9-8fa062fa4b3f.gif)

# おわりに
今回は、マスに対してクリックすると「X」が表示されるインタラクションを実装しました。次のページに現段階のソースファイルを示します。

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

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

https://qiita.com/banana_bancho/items/81730326c004e52c6aad