Square组件
import React from 'react';
//import { useState } from 'react';
export default function Square({ value, onSquareClick }) {
return (
<button className="square" onClick={onSquareClick}>
{value}
</button>
);
Board组件
import React from 'react';
import Square from '../Square';
//import Game from '../Game';
import { useState } from 'react';
//这个辅助函数用于判断谁是获胜者
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;
}
//状态提升:将子组件的状态提升到父组件
//要从多个子组件收集数据,或让两个子组件相互通信,请改为在其父组件中声明共享 state。父组件可以通过 props 将该 state 传回给子组件。这使子组件彼此同步并与其父组件保持同步。
export default function Board() {
const [squares, setSquares] = useState(Array(9).fill(null));
const [xIsNext, setxIsNext] = useState(true);
function handleClick(i) {
//如果方块不为空或者已经决出获胜者,游戏就终止
if (squares[i] || calculateWinner(squares)) {
return;
}
//改变点击的Square状态,并更新数组
//思考:为什么不直接改变原数组的值,而是要重新生成一个数组再赋值?
//1、使得复杂的功能(时间旅行)容易实现。2、降低Diff算法的成本
const nextSquares = squares.slice();
if (xIsNext) {
nextSquares[i] = 'X';
} else {
nextSquares[i] = 'O';
}
setSquares(nextSquares);
setxIsNext(!xIsNext);
//xIsNext = !xIsNext;
}
//如果游戏没有结束,就显示下一步该谁走。如果游戏结束就显示获胜者
const winner = calculateWinner(squares);
let status;
if (winner) {
status = '获胜者是' + winner;
} else {
status = '下一步该轮到' + (xIsNext ? 'X' : 'O');
}
return (
<>
<div className="board-row">
<Square value={squares[0]} onSquareClick={() => handleClick(0)} />
<Square value={squares[1]} onSquareClick={() => handleClick(1)} />
<Square value={squares[2]} onSquareClick={() => handleClick(2)} />
</div>
<div className="board-row">
<Square value={squares[3]} onSquareClick={() => handleClick(3)} />
<Square value={squares[4]} onSquareClick={() => handleClick(4)} />
<Square value={squares[5]} onSquareClick={() => handleClick(5)} />
</div>
<div className="board-row">
<Square value={squares[6]} onSquareClick={() => handleClick(6)} />
<Square value={squares[7]} onSquareClick={() => handleClick(7)} />
<Square value={squares[8]} onSquareClick={() => handleClick(8)} />
</div>
<h1>{status}</h1>
</>
);
}