Reactチュートリアルをこなしてみてその1

# Reactチュートリアルをこなしてみてその1

公式チュートリアルをやってみたのでアウトプットします。

[リポジトリはこちら](https://github.com/shitikamiyako/React_Tutorial1)
## Reactのコンポーネントについて

```jsx

class ShoppingList extends React.Component {
    render() {
        return {
            <div className="shopping-list">
                <h1>Shopping List for {this.props.name}</h1>
                <ul>
                    <li>Instagram</li>
                    <li>WhatsApp</li>
                    <li>Oculus</li>
                </ul>
            </div>
        }
    }
}

```

ReactはJSXという書式を使って書いていきます。
上記のコードを見ればわかるようにJavascriptでもHTMLのように書けるような書式といった感じです。
上記のようなコードひとまとまりを指して、Reactでは`コンポーネント`と呼ぶそうです。
`ShopppingList`はいわゆるクラスに相当する部分ですね。
つまり、コンポーネントは`React.Component`を継承したクラスを指すという見方もできます。
このコンポーネントにいろいろ書いてそれを`render()`メソッドでうまいことやったあと、returnで描画したいHTMLを返すというのがReactの基本みたいです。
ちなみにreturn以下のHTML部分はJavascriptで書くと

```js
return React.createElement('div', {className: 'shopping-list'},
  React.createElement('h1', /* ... h1 children ... */),
  React.createElement('ul', /* ... ul children ... */)
);

```

上記のようになるそうです。
JSXのがわかりやすいですね。
単なるHTMLとは`class`が`className`になっているところや`<ShoppingList />`と書けばそれ全体を指定することもできます。
例えば`<div />`としてやれば、divタグすべてが指定されます。

## Propsについて

では公式チュートリアルのように三目並べを作っていきます。
この三目並べは

- Square
- Board
- Game

の3つのコンポーネントから構成されます。
実はこの3つのコンポーネントは親子関係ができていたりするのですが、それは少しずつ見ていくとしてまずは盤面を作ってみます。
そのためのコードが以下の部分です。

```jsx:src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

class Square extends React.Component {
    render() {
        return (
            <button className="square">{this.props.value}</button>
        );
    }
}

class Board extends React.Component {
    renderSquare(i) {
        return <Square value={i} />;
    }

    render() {
    const status = 'Next player: X';

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

```

現時点ではSquareがマス単位、Boardが盤面全体に対してのコンポーネントだと思ってください。
ここで重要なのは`renderSquare`メソッドでSquareに対して値(`value={i}`)をパスしているところです。
少し複雑なのですが要は

`renderSquare(i) { return <Square value={i} />;}`

この部分が

`{this.renderSquare(i)}`

として描画されることになるのですが、そのためにまず`renderSquare`メソッドでSquareコンポーネントに対して各マスの値は`value={i}`だよという指示を出します。
すると、Squareコンポーネント側は`{this.props.value}`でそれを受け取ります。
Reactではこのようにあるコンポーネントからコンポーネントへと情報を流していくように書いていくのですが、そこでパスされていくのがpropsということになるわけですね。
あとはSquareコンポーネントで各マスはボタンだよという定義がなされているので`{this.renderSquare(i)}`の各部分は0~9のマスのボタンとして描画されるということです。
また、流れでさらっと書いてますがBoardは盤面全体を表すということで上記のような過程を踏んでいます。
つまり、Squareコンポーネントでマスがどういうものなのか(今回はボタン)を定義して、それをBoardで具体的な盤面として表しているという感じです。
よって、BoardはSquareに対して親の関係にあたるということになります。

## stateについて

では、次にSquare コンポーネントがクリックされた場合に “X” と表示されるように変えてみます。

```jsx

class Square extends React.Component {
 render() {
   return (
     <button className="square" onClick={() => alert('click')}>
       {this.props.value}
     </button>
   );
 }
}

```

SquareコンポーネントのbuttonタグにonClickプロパティを追加し、その引数として関数を設定しています。
この場合、マスをクリックしたらアラートがポップアップするということになりますね。
これでアクションを設定したので、あとはSquareコンポーネントがこのアクションを記憶できるように処理を書いていきます。
Reactではそのような処理を定義するのに`state`というものを使います。
では書いてみましょう。

```jsx

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button className="square" onClick={() => this.setState({value: 'X'})}>
        {this.state.value}
      </button>
    );
  }

}
```

まずコンストラクタを追加します。
コンストラクタは初期化やプリセットの値を用意するために定義するものですが、今回はstateの状態を初期化するために用意することになります。
次に`render()`メソッド側も手を入れます。
まず、onClickプロパティの引数を`this.setState()`に変更します。
setStateはstateを変更するためのメソッドです。
つまり、現状ではBoardから受け取ったpropsをコンストラクタで引き取り`this.state`にvalueを初期化して代入したあとに、Squareの`render()`メソッドにおいてそれを書き換えているという処理になっています。
これで、どのマス目をクリックしても`X`マークが表示されることになります。

## リファクタリングしていく

基本の処理ができたところでここからはリファクタリングを行って三目並べを完成させていきます。
Reactではこのあと行うState のリフトアップのように実装→リファクタリングを繰り返していくような流れでコードを書いていくのが基本的な流れになるみたいです。

### Stateのリフトアップ

さて、先述の通り現在はSquareコンポーネントでstateの状態が管理されています。
しかし、ゲームが今どういう状態なのかということはより上位のコンポーネントで管理をしたい方が都合がいいでしょう。
今回の場合は、BoardでStateを管理し、各Squareにpropsを渡すことでどのマスに何を描画するかを決定するという状態にしたいわけです。
ということでSquareからBoardへとStateの管理を移譲していきます。
では見ていきましょう。

```jsx

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state= {
      squares: Array(9).fill(null),
    };
  }

    renderSquare(i) {
      return <Square value={this.state.squares[i]} />;
  }
}

```

まず、constructorをBoardコンポーネントに移します。
ここからBoardでvalueとして0~8の値を渡したあと、SquareのStateでXマークに値を書き換えていたのをBoardから直接個別の値を渡すようにしたいので`renderSquare()`を上記のようにします。
次に、ここからonClickの挙動を変更します。
今、マス目に何が入っているかの管理をBoardコンポーネントに移しましたが、各マスにそれを反映させるためにはSquareがBoardに移したstateを更新できるようにしなければいけません。
しかし、stateはいわゆる`private`なものなので、コンポーネント外からの直接の変更は受け付けません。
なので、BoardからSquareのonClickにstateを変更するような関数を渡して、クリックのアクションでそれを呼び出す形でstateを変更する処理を実装します。
そのために`renderSquare()`を以下のように変更します。

```jsx

renderSquare(i) {
  return (
    <Square value={this.state.squares[i]} onClick{() => this.handleClick(i)} />
  );
}

```

そして、Squareコンポーネントを以下のように書き換えます。

```jsx

class Square extends React.Component {
  render() {
    return (
      <button> className="square" onClick={() => this.props.onClick()}
        {this.props.value}
      </button>
    );
  }
}

```

ここまで来たらひとまず現状を整理しましょう。
まず、BoardからSquareに渡されているpropsにはvalueとonClickなります。
valueはマスの値、onClickはこのあと定義するstateの状態を変更する`handleClick(i)`メソッドとなります。
そして、Squareにおいてそれらを`this.props.value`及び`this.props.onClick()`として呼び出しています。
厳密には以下(チュートリアルから引用)のような処理になるようです。

> 1. 組み込みのDOMコンポーネントである `<button>` に onClick プロパティが設定されているため React がクリックに対するイベントリスナを設定します。
> 2. ボタンがクリックされると、React は Square の render() メソッド内に定義されている onClick のイベントハンドラをコールします。
> 3. このイベントハンドラが this.props.onClick() をコールします。Square の onClick プロパティは Board から渡されているものです。
> 4. Board は Square に onClick={() => this.handleClick(i)} を渡していたので、Square はクリックされたときに this.handleClick(i) を呼び出します。
> 5. まだ handleClick() は定義していないので、コードがクラッシュします。Square をクリックすると、“this.handleClick is not a function” といった赤いエラー画面が表示されるはずです。

ちなみにReactではイベント(ここではクリックという行為)に対して`on[Event](ex.onClick)`、イベントを処理するメソッドには `handle[Event](ex.handleClick)` という名前を付けるのが慣習となっているようです。
では、未定義の`handleClick`を定義していきましょう。

```jsx

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = 'X';
    this.setState({squares: squares});

  }

  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }

  render() {
    const status = 'Next player: X';

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}


```

`handleClick()`メソッド内に`set.State()`メソッドを入れることでstateの変更を行っています。
では、改めて現状を整理すると

- SquareコンポーネントはBoard コンポーネントから値を受け取って、クリックされた時はそのことをBoardコンポーネントに伝えるだけになった。
- Boardのstateが変更されると、個々のSquareコンポーネントもそれに合わせて再度レンダーされる。
- よって全てのマス目の状態はBoardコンポーネント内で保持され、**SquareコンポーネントはBoardコンポーネントに制御された状態**となった。

ということになります。

さて、ここで注目するべきは`const squares = this.state.squares.slice();`という部分です。
`slice()`は配列のコピーを作成するメソッドですが、わざわざ`squares`のコピーを作成するより、直接`squares`を書き換えるような形でいいのでは？ という疑問が残ると思います。
それに対する解答が次に見ていくイミュータビリティという考え方です。

### イミュータビリティについて

イミュータビリティ（immutability; 不変性）ということで、データを変更する際に元データに対して、**書き換えではなく置き換えを行う**というアプローチをする考え方です。
チュートリアルでの例を見てみます。

```jsx

// ミューテート(書き換え)でのアプローチ
var player = {score: 1, name: 'Jeff'};
player.score = 2;
// Now player is {score: 2, name: 'Jeff'}

// 置き換えでのアプローチ

var player = {score: 1, name: 'jeff'};

var newPlayer = Object.assign({}, player, {score: 2});

//  Now player is unchanged, but newPlayer isn`t {score: 1, name: 'Jeff'}, however {score: 2, name: 'Jeff'}

```

`Object.assign`オブジェクトのコピーを作るメソッドです。
第一引数に空のオブジェクト、第二引数にコピーするオブジェクトを指定します。
さらにここで第三引数で参照したいオブジェクト指定することで、コピーしたオブジェクトの参照元を変更できます。
つまり、`var newPlayer = Object.assign({}, player, {score: 2});`は**playerオブジェクトをコピーしてscoreプロパティは{score: 2}を参照してください**という意味になるわけです。
このあたりはオブジェクト指向について少し触れたことがある人は理解しやすいと思います。

では、なぜこういった手法を取るのかというと公式のチュートリアルでは理由が3つ挙げられています。

1. 複雑な機能が簡単に実装できる

これはこのあと実装するタイムトラベル、つまりは手順の巻き戻しの機能を実装として例が挙げられています。
手順を巻き戻すということは例えば、playerオブジェクトのscoreが変動するということになるのですが、ここで書き換えの手法を使ってしまうとscoreプロパティを変更するのにいくつかの行程を踏む可能性が出てきてしまいます。
上記の例だけでも、手順を戻したり進めたりするだけで其の度に`player.score`に値を代入し直さないといけなくなります。
対して、置き換えの手法取ると参照するオブジェクトをplayerとnewPlayerとで切り替えればいいだけなので簡単ですね。

2. 変更の検出が容易

概ね1と同じような理由ですがチュートリアルからの引用を載せておきます。
> ミュータブル (mutable) なオブジェクトは中身が直接書き換えられるため、変更があったかどうかの検出が困難です。ミュータブルなオブジェクト変更の検出のためには、以前のコピーと比較してオブジェクトツリーの全体を走査する必要があります。
> イミュータブルなオブジェクトでの変更の検出はとても簡単です。参照しているイミュータブルなオブジェクトが前と別のものであれば、変更があったということです。

3. React の再レンダータイミングの決定がしやすい

これも上記2つと同じような理由ですね。
Reactはフロントエンドの技術なので画面をどう描画するかということを処理する役割を持ちます。
なので、画面が切り替わったりあるいは画面遷移がなくてもその場で今回のように手順の変更等があり、画面に変更がある場合などはその都度処理をするのですがその際、stateのどの部分に変更があったのかということがわからないと、それを探すのに差分をすべて探してしまいます。そうなると、当然処理は重くなり再描画が遅くなってしまいます。
しかし、置き換えの手法を用いると参照オブジェクトの切り替えだけで事が済むのでReactはstate内のどの部分に変更があったのか検知をして、差分の比較を変更があったオブジェクトのみで行うことができます。
すると、Reactは画面のどの部分を再描画したらいいのか判断をし、変更の必要のない部分は再描画を行わないという処理を実行するので処理に負担をかけずに済むわけですね。

以上、3点については以下の記事が簡潔にわかりやすくまとまっています。

[Reactにおけるstateのイミュータビリティ](https://qiita.com/s_harada/items/71a14ec07786682ec7e6)

### 関数コンポーネント

さて、Boardコンポーネントに盤面の管理を完全に移行したのでSquareコンポーネントはもうpropsを受け取ってそれに基づいて描画内容を返す役割しかありません。
なので、クラスのコンポーネントではなくより簡潔な関数のコンポーネントに書き直します。
関数コンポーネントはstateを持たず、`render()`メソッドのみを持つコンポーネントのことを指します。


```jsx

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

```

このようになります。
クラスではなくなったので`this.props`は`props`になりました。
ちなみにそれと合わせて`onClick={() => this.props.onClick()}`は` onClick={props.onClick} `と書き換えることができるみたいなのでそれに合わせておきます。

### 手番の処理

先手と後手の概念を付与します。
まずは、Boardコンポーネントのコンストラクタの部分を変更します。

```jsx

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }
}

```

`xIsNext`プロパティを新たに追加しました。
これを元に真偽値を判断してtrueである場合Xをそうでない場合はOを描画するように処理を書いていきます。
stateの状態を変更するメソッドは`handleClick()`メソッドでしたね。
ついでにrender()メソッド内も変更して誰の手番か表示するようにします。

```jsx

handleClick(i) {
  const squares = this.state.squares.slice();
  // 真偽値判断
  squares[i] = this.state.xIsNext ? 'X':'O';
  // 呼び出されるたびにxIsNextの状態を反転させる
  this.setState({
    squares: squares,
    xIsNext: !this.state.xIsNext,
  });
}

render() {
  const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}

```

### 勝者の判定

最後に勝者の判定を実装します。
チュートリアルでは以下の関数をコピペしろという支持があるのでコピペします。

```jsx

function calculateWinner(squares) {

  // squareコンポーネントに与える配列のリスト
  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],
  ];

  // 9 つの square の配列が与えられると、この関数は勝者がいるか適切に確認し、'X' か 'O'、あるいは null を返す。
  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;
}

```

例えば`i = 0`出会った場合は`const[a,b,c] = [0,1,2]`となります。
つまり`squares[0,1,2]`となるわけですね。
で、この`[0,1,2]`は盤面のマスの位置を示しています。
なのでここまで書けばもうお分かりかと思いますが、

`if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) `は`squares(XかOどちらかのプレイヤー)`のマス目が3連になっているかの判定ということになります。
`const lines`はつまり、縦横斜めで3連になる組み合わせを表していたということです。


次にこれを呼び出して勝利判定を行うようにします。
Boardコンポーネントの`render()`部分を変更しましょう。

```jsx

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

```

最後に、`handleClick`メソッドを書き換えてゲームの決着がすでについている場合もしくは、クリックされたマス目が埋まっている場合にreturnするような処理を実装します。


```jsx

 handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }


```

これで三目並べ自体は完成となりました。

## タイムトラベル機能の追加

最後に手番を巻き戻せるようにタイムトラベル機能を実装します。
要は過去の手番を保存しておく配列を用意すればいいわけですね。
手番の状態はsquaresの配列で表現されるということは先程確認しました。
チュートリアルから引用すると

 ```jsx
history = [
  // Before first move
  {
    squares: [
      null, null, null,
      null, null, null,
      null, null, null,
    ]
  },
  // After first move
  {
    squares: [
      null, null, null,
      null, 'X', null,
      null, null, null,
    ]
  },
  // After second move
  {
    squares: [
      null, null, null,
      null, 'X', null,
      null, null, 'O',
    ]
  },
  // ...
]

 ```

 このような感じで保存しておけるようにしたいということになりますね。
 では進めていきます。

 ### stateのリフトアップ再び

 上記を見るとわかると思いますが、historyは手番をすべて管理している状態と言えます。
 そして、historyは状態が常に変化していくこともここまでくればわかると思います。
 つまり、historyはstateで管理され、そうなると盤面のマスの状態はhistoryから引っ張ってくればいい=propsとしてやり取りするような処理を書けるということになりますね。
 なので、Boardよりさらに上位のGameコンポーネントを作り、そこにstateをリフトアップしていくというのが今回やることです。

 では、作業していきましょう。
 まずはコンストラクタの移行ですね。

 ```jsx

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      xIsNext: true,
    };
  }

  render() {
    return (
      <div className="game">
        <div className="game-board">
          <Board />
        </div>
        <div className="game-info">
          <div>{/* status */}</div>
          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }
}


 ```

次にGameコンポーネントの`render()`をhistoryが使われるように変更します。
Boardコンポーネントから`render()`のうちゲームテキスト表示の処理をこちらに移植します。
また、それに伴い`handleClick()`も同時に移植してしまいます。

```jsx

  handleClick(i) {
    const history = this.state.history;
    const current = history[history.length - 1];
    const squares = this.current.squares.slice();
    if(calculateWinner(squares) || squares[i]) {
      return;
    }

    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      xIsNext: !this.state.xIsNext,
    });
  }

  render() {
    // historyを引っ張ってくる
    const history = this.state.history;
    // historyに保存されているsquares配列より最新のものを取得
    const current = history[history.length - 1];
    const winner = calculateWinner(current.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
        <div className="game-board">
          <!-- ゲームのステータステキストを表示 -->
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }



```

 最後にリフトアップに合わせてBoardコンポーネントをpropsを受け取る形に書き換えます。
 やることは

- コンストラクタの削除
- `this.state.squares`を`this.props.squares`へと置き換え
- `this.handleClick`を`this.props.onClick`へと置き換え
- `render()`のうち移植した部分を削除

- `handleClick()`の削除


こう見るとリフトアップのポイントはどのプロパティをリフトアップするのか(=propsとして受け取ることになるのか)ということを理解することなのかもしれませんね。

 ```jsx

class Board extends React.Component {

  renderSquare(i) {
    return(
      <Square value={this.props.squares[i]} onClick{() => this.props.onClick(i)} />
    );
  }

  render() {
    return (
      <div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

 ```

### 過去の着手の表示

過去の手番に「ジャンプ」するためのボタンの一覧を作成していきます。
Gameコンポーネントの`render()`に処理を追加をしていきます。

```jsx

render() {
  const history = this.state.history;
  const current = history[history.length - 1];
  const winner = calculateWinner(current.squares);

  const moves = history.map((step, move) => {
    const desc = move ? 'Go to move #' + move :'Go to game start';

    return(
      <li>
        <button onClick={() => this.jumpTo(move)}>{desc}</button>
      </li>
    );
  });

    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <!-- 手番ボタンの表示 -->
          <ol>{moves}</ol>
        </div>
      </div>
    );

}

```

`map()`はある配列を別の配列に作り直すことができます。
チュートリアルでは以下のような例で説明されています。

```jsx

const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]

```

historyには手番がsquaresの配列の形ですべて保存されているわけですから、手番を戻す際にhistoryから該当する手番の配列を取得して返したいということになるわけです。
故に上記のようなコードになったわけですが、このままでは`jumpTo()`が未定義であることと、keyの概念が欠如しているのでエラーが出ます。
Keyについてはプロパティにおけるキー、またはデータベースにおけるIDなどと同じような考え方で、Reactではリストのレンダーに関してその履歴に対し個々にユニークIDを持っているわけです。
これはどういうことかというと例えば今回は手番が進むたびに画面が更新されるわけですが、その個々の描画がそれぞれIDを持つということになります。
故にこのIDを用いて、履歴のインデックスとすることが可能というわけですね。
ちなみにKeyはこちらから参照することはできず、Reactから自動的に使用されるようです。

閑話休題、よって`jumpTo()`の実装とKeyの明示を行わなければいけません。
以下の通りに勧めていきます。

```jsx
class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      // 何手目であるかを表すプロパティを追加
      stepNumber: 0,
      xIsNext: true,
    };
  }

  handleClick(i) {
    // ある手番(A)から過去手番(B)に戻り、そこから新しい手を打った場合、これまでのAまでの手番を参照せずにそれらの履歴を削除する
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if(calculateWinner(squares) || squares[i]) {
      return;
    }

    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares
      }]),
      // 手番の巻き戻しを行い、そこから新しい手を打った場合の手番の更新
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext.
    });
  }


  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) === 0,
    });
  }

  render() {
    // this method has not changed
    const moves = history.map((step, move) => {
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        <li key={move}>
          <button onClick={() => this.jumpTo(move)}>{desc}</button>
        </li>
      );
    });

     return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <!-- 手番ボタンの表示 -->
          <ol>{moves}</ol>
        </div>
      </div>
    );
  }
}


```

まず、`render()`の描画の部分に`<li key={move}>`という形でKeyを明示してやります。
また、何手目の状態であるかを管理するための`stepNumber`プロパティを追加しています。
それに伴い、`render()`に`current`変数を追加し、historyからこのプロパティを用いて現在選択されている手番を取得するように変更します。
次に、その`stepNumber`が更新されるように。`jumpTo()`を定義していきます。
ちなみに先程からいきなり`step`及び`move`が引数として登場していますが、コードを見る限りでは`step`は手番、moveは`squares`の配列を表しているみたいです。
従って、`jumpTo()`は手番を更新し、かつそれに伴い`xIsNext`つまりはプレイヤーがどちらであるか設定しているということになります。

ここまで来たら最後に`handleClick()`を更新します。
主に巻き戻しを行うのに備えての指定の仕方の変更ですね。
上記のコードにコメントしてありますが、例えば`setState()`の部分だと`stepNumber`のプロパティを`stepNumber: history.length`としています。
これは先程の`jumpTo()`が単純に`step`を手番として管理していたのに対し、巻き戻しを行った際はそれでは管理できないので`history.length`から引っ張ってくるということになるわけです。

これで、React公式チュートリアルは完了です。
お疲れ様でした、全体のコードは以下のようになっていると思います。

<details><summary>最終的なコード</summary><div>

```jsx


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

class Board extends React.Component {
  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}
        onClick={() => this.props.onClick(i)}
      />
    );
  }

  render() {
    return (
      <div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [
        {
          squares: Array(9).fill(null)
        }
      ],
      stepNumber: 0,
      xIsNext: true
    };
  }

  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? "X" : "O";
    this.setState({
      history: history.concat([
        {
          squares: squares
        }
      ]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext
    });
  }

  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) === 0
    });
  }

  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

    const moves = history.map((step, move) => {
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        <li key={move}>
          <button onClick={() => this.jumpTo(move)}>{desc}</button>
        </li>
      );
    });

    let status;
    if (winner) {
      status = "Winner: " + winner;
    } else {
      status = "Next player: " + (this.state.xIsNext ? "X" : "O");
    }

    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={i => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{moves}</ol>
        </div>
      </div>
    );
  }
}

// ========================================

ReactDOM.render(<Game />, document.getElementById("root"));

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;
}



```

</div></details>