React公式チュートリアルの三目並べに追加機能を実装してみた #3（トグルボタンを追加しろ！編）

## はじめに
はい、ということでReact公式チュートリアル追加機能実装第三弾やっていきたいと思います。

今回実装する機能はこちら↓
「Add a toggle button that lets you sort the moves in either ascending or descending order.」（日本語訳：動きを昇順または降順に並べ替えることができるトグル ボタンを追加する。）です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/746dbab7-0c0c-e469-613c-d39a5c4f0220.png)

、、、、どういう機能だ？？

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/46191b94-8577-9902-565d-d8dad731e947.gif)

今のところ機能はこのようになっています。
このボード履歴のボタンの順序を並べ替えられるようになればいい、、のでしょうか？

はい、この記事ではそういうことにしておきましょう。（正しいニュアンスわかる人いたら教えてください(꒪ཀ꒪)）

それでは早速実装に移っていきます！

## 実装

実装の方針としては、useStateで順序が正になっているか逆になっているか状態を管理してあげます。
正の場合は正の順でボタンを並べる、逆だったら逆の順で並べるようにボタンを描画してあげて、そのステートを切り替えるボタンも実装してあげましょう。

```App.js
export default function Game() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [currentMove, setCurrentMove] = useState(0);
  const [isAscending, setIsAscending] = useState(true);  //←追加
  const xIsNext = currentMove % 2 === 0;
  const currentSquares = history[currentMove];

  function handlePlay(nextSquares) {
    const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
    setHistory(nextHistory);
    setCurrentMove(nextHistory.length - 1);
  }

  function jumpTo(nextMove) {
    setCurrentMove(nextMove);
  }

  const moves = history.map((squares, move) => {
    const description = move > 0 ? 'Go to move #' + move : 'Go to game start';
    const buttonClass = move === currentMove ? 'game-info-btn current-move' : 'game-info-btn';
    return (
      <li className="game-info-item" key={move}>
        <button className={buttonClass} onClick={() => jumpTo(move)}>
          {description}
        </button>
      </li>
    );
  });

  function toggleSortOrder() {
    setIsAscending(!isAscending);  //←状態を切り替え
  }

  const sortedMoves = isAscending ? moves : moves.slice().reverse();  //←正の順で並べるか、逆の順で並べるか

  return (
    <div className="game">
      <div className="game-board">
        <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
      </div>
      <div className="game-info">
        <button className="toggle-button"  onClick={toggleSortOrder}>Toggle Sort Order</button>  //←追加
        <ol className="game-info-list">{sortedMoves}</ol>
      </div>
    </div>
  );
}
```

そしてデザインも少し整えてあげましょう。

```App.css
.toggle-button {
  background-color: #8affc1;
  padding: 15px 30px;
  border: none;
  border-radius: 5px;
  font-size: 20px;
  cursor: pointer;
  transition: background-color 0.3s;
  text-align: center;
  display: inline-block;
}

.toggle-button:hover {
  background-color: #45ff9c;
}
```

はい、これで動くようになったか`http://localhost:3000/`で確認してみましょう！

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3577451/50c1c69b-cfc1-e8ef-8af7-c79f19a9ed9c.gif)

完璧ですね！

ただ、状態を切り替えている処理の箇所は別の書き方でも実装できるのでそちらも紹介しておこうかなと思います。

```App.js
function toggleSortOrder() {
    // setIsAscending(!IsAscending); ←さっきの書き方
    setIsAscending(prevIsAscending => !prevIsAscending);// ←新しい書き方
  }

```

はい、こちらです。
、、、、`prevIsAscending`なんてどこにも出てこないじゃん！！と思いますよね。（僕も思います）
ですがどうやらReactの機能で「関数型のstate更新」というものがあるらしいです。
こちらの`prevIsAscending`は前の`IsAscending`として扱うことができるとのことです。
つまり、「"前"のステートを表す変数」的なニュアンス、、、
ここら辺の説明に関しては[こちらの記事](https://qiita.com/jonakp/items/7d768bc680b8a7a5e84f)で詳しく説明されていたのでこちらをご参照くださいm(_ _)m


ちょっと話が脱線してしまいましたが、追加機能第三弾も無事実装できたということで今回はこれにて終了です！


### 次の記事↓
[React公式チュートリアルの三目並べに追加機能を実装してみた #4（勝利のマスを強調しろ！編）](https://qiita.com/Ryukuu0919/items/c44c5649d1f08b8e31f7)

### 他の関連記事↓
[React公式チュートリアルの三目並べに追加機能を実装してみた #1（現在のターンを示せ！編）](https://qiita.com/Ryukuu0919/items/50dc599c4f5acf4478b9)
[React公式チュートリアルの三目並べに追加機能を実装してみた #2（ループ処理でボードを表示しろ！編）](https://qiita.com/Ryukuu0919/items/7ec65b2964f611454c5e)
[React公式チュートリアルの三目並べに追加機能を実装してみた #5（各ターンで打った手を記憶しろ！編）](https://qiita.com/Ryukuu0919/items/cdcd08987f6b727798f9)
[React公式チュートリアルの三目並べに追加機能を実装してみた #6（AWSで公開しろ！編）](https://qiita.com/Ryukuu0919/items/eec4be8768b57601f27a)