Skip to content

Instantly share code, notes, and snippets.

@leewc
Last active August 3, 2022 09:23
Show Gist options
  • Save leewc/0f8331ddedb8cf1f86601a60b97fa11a to your computer and use it in GitHub Desktop.
Save leewc/0f8331ddedb8cf1f86601a60b97fa11a to your computer and use it in GitHub Desktop.
React Learning : Convert Tutorial into one with Hooks
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
)
}
function Board(props) {
function renderSquare(i) {
return <Square
value={props.squares[i]}
onClick={() => props.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>
);
}
// With learnings from https://github.com/codeSTACKr/react-tic-tac-toe-hooks/blob/master/src/components/Game.js
function Game (props) {
const [history, setHistory] = React.useState([Array(9).fill(null)]);
const [stepNumber, setStepNumber] = React.useState(0);
const [xIsNext, setXIsNext] = React.useState(true);
//move these up here to avoid computation of winner 2x
const current = history[stepNumber];
const winner = calcWinner(current);
function jumpTo(step) {
setStepNumber(step);
setXIsNext(step % 2 === 0);
}
function handleClick(i) {
const historyPoint = history.slice(0, stepNumber + 1);
const current = historyPoint[historyPoint.length - 1];
// OR use the same: const current = historyPoint[stepNumber];
const sq = current.slice();
if (winner || sq[i]) {
return;
}
sq[i] = xIsNext ? 'X' : 'O';
// This breaks --> setHistory(historyPoint.concat(sq)); even if adding []
setHistory([...historyPoint, sq]);
//history.length is wrong, will go out of bounds
setStepNumber(historyPoint.length);
setXIsNext(!xIsNext);
}
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>
)
})
const status = 'Next player: ' + (xIsNext ? 'X' : 'O');
return (
<div className="game">
<div className="game-board">
<Board squares={current}
onClick={(i) => handleClick(i)}/>
</div>
<div className="game-info">
<div>{winner ? '!!! Winner:' + winner : status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
// ========================================
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Game />);
function calcWinner(squares) {
const winningLines = [
[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 < winningLines.length; i++) {
const [a,b,c] = winningLines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment