Reactの公式チュートリアルで作成する完成版アプリをHookを使って書き直してみました。
あまり大したことはやっていないのですが、Hook化するにあたりクラスコンポーネントを関数コンポーネントに書き直し、ステート管理はHookのuseStateを使いました。関数は全てアロー表記で書いています。
Hook化でアプリの挙動に変わりはありませんが、元のコードより2割ほど行数は減りました。
修正は以下のとおりindex.jsのみです。
import React, { useState } from 'react'; import ReactDOM from 'react-dom'; import './index.css'; const 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; }; const Square = ({ value, onClick }) => { return ( <button className="square" onClick={onClick}> {value} </button> ); }; const Board = ({ squares, onClick }) => { const renderSquare = (i) => { return <Square value={squares[i]} onClick={() => onClick(i)} />; }; return ( <div> <div className="board-row"> {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} </div> <div className="board-row"> {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} </div> <div className="board-row"> {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} </div> </div> ); }; const Game = () => { const [history, setHistory] = useState([{ squares: Array(9).fill(null) }]); const [stepNumber, setStepNumber] = useState(0); const [xIsNext, setXIsNext] = useState(true); const handleClick = (i) => { const historySlice = history.slice(0, stepNumber + 1); const current = historySlice[historySlice.length - 1]; const squares = current.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } squares[i] = xIsNext ? 'X' : 'O'; setHistory( historySlice.concat([ { squares: squares, }, ]) ); setStepNumber(historySlice.length); setXIsNext(!xIsNext); }; const jumpTo = (step) => { setStepNumber(step); setXIsNext(step % 2 === 0); }; const current = history[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={() => jumpTo(move)}>{desc}</button> </li> ); }); let status; if (winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (xIsNext ? 'X' : 'O'); } return ( <div className="game"> <div className="game-board"> <Board squares={current.squares} onClick={(i) => handleClick(i)} /> </div> <div className="game-info"> <div>{status}</div> <ol>{moves}</ol> </div> </div> ); }; // ======================================== ReactDOM.render(<Game />, document.getElementById('root'));