React入門10: タイムトラベル(2)

# はじめに
私自身の復習兼、備忘録的な意味もあり、複数回の記事に渡って 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入門４: リファクタリング [リフトアップ編]](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) (今回)
1. [React入門11: タイムトラベル(3)](https://qiita.com/banana_bancho/private/0d3cf7e1b1ebbf20c5e0)

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

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

## 今回の目的
前回の記事では、盤面の状況を記録するために ```Game``` コンポーネントを実装し、```Board``` コンポーネントからのリフトアップをしました。今回の記事では、記録した情報を表示していきます。

# タイムトラベル(2)
次のページで、前回のソースファイルを確認できます。

https://codesandbox.io/p/sandbox/react-tutorial9-kj7rcq

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

https://qiita.com/banana_bancho/private/c674872e32fcb52bb2a0

## ```map()``` メソッド
ソースコードを編集する前に、```map()``` メソッドについて説明していきます。このメソッドは、各要素に対してアロー ```=>``` の後ろに記述した処理の結果を配列で返します。処理が複数の文となる場合は、コードブロック(文を波括弧 ```{}``` で囲ったもの)で記述します。

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

```map()``` メソッドは次のような構文になります。

### 構文1
配列の要素のみを利用したい場合は、次の構文を利用します。```仮引数``` には ```配列``` の要素が渡されます。
```js: map() メソッドの構文1
配列.map((仮引数) => 仮引数ごとに実行する処理)
```

例えば、次の ```map()``` メソッドを実行すると、コンソールに「```[2, 3, 4]```」と出力されます。これは、```[1, 2, 3]``` という配列が、```map()``` メソッド内の処理で、要素ごとに ```x + 1``` という処理をされたためです。

```js: map() メソッドの使用例1
console.log([1, 2, 3].map((x) => x + 1));
```

### 構文2
配列の要素とその要素番号(インデックス)を利用したい場合は、次の構文を利用します。```仮引数1``` には ```配列``` の要素、```仮引数2``` には ```仮引数1``` の要素番号が渡されます。
```js: map() メソッドの構文2
配列.map((仮引数1, 仮引数2) => 要素ごとに実行する処理)
```

例えば、次の ```map()``` メソッドを実行すると、コンソールに「```[0, 2, 6]```」と出力されます。これは、```[1, 2, 3]``` という配列が、```map()``` メソッド内の処理で、要素ごとに ```x + 1``` という処理をされたためです。

```js: map() メソッドの使用例2
console.log([1, 2, 3].map((x, i) => x * i));
```

## 過去の手番の表示
JavaScript の ```map()``` メソッドを使って、```history``` 配列の要素数だけ、ボタンを表示していきます。

App.js の ```Game``` コンポーネントを次のように変更します。
- ```moves``` 配列を定義する
    - ```history``` 配列に ```map()``` メソッドで処理をした後の返り値を代入する
        - ```map()``` メソッドの仮引数は、```squares``` と ```move``` とする。
        - ```history``` 配列の要素数だけ ```<li>``` 要素で囲まれた ```<button>``` 要素を表示する
        - ボタンには ```i番目の手番``` というテキストを表示させる (```i``` : 要素番号)
- レンダリング内容の変更
    - ```<Board>``` コンポーネントを ```<div>``` 要素で囲む
    - ```<ol>``` 要素で ```moves``` 配列の内容を表示する
    - ```<ol>``` 要素も ```<div>``` 要素で囲む
    - 全体をフラグメント ```<>``` で囲む

```jsx:App.js の Game コンポーネント
export default function Game() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [xIsNext, setXIsNext] = useState(true);
  const currentSquares = history[history.length - 1];
  
  const moves = history.map((squares, move) => (
    <li>
      <button>{move} 番目の手番</button>
    </li>
  ));

  function handlePlay(nextSquares) {
    setHistory([...history, nextSquares]);
    setXIsNext(!xIsNext);
  }

  return (
    <>
      <div>
        <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
      </div>
      <div>
        <ol>{moves}</ol>
      </div>
    </>
  );
}
```

次に実行結果を示します。手番が交代するごとにボタンが表示されるようになりました。なお、このボタンはイベントを実装していないので、クリックをしても何も実行されません。

![output_video.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/83f5b731-fa70-73fe-6f91-7d5cb5d6ebc0.gif)


# おわりに
今回は、タイムトラベルを実装するにあたり、手番を示すボタンを実装していきました。次のページに現段階のソースファイルを示します。

https://codesandbox.io/p/sandbox/react-tutorial10-k8wwf8

次回は、このボタンをクリックすることで過去の手番に戻れるようにしていきます。

https://qiita.com/skm_bnn/items/0d3cf7e1b1ebbf20c5e0