javascript - 满足条件时停止更新(React tic-tac-toe)
问题描述
我正在 React 中创建一个快速井字游戏实现,并遇到了一个问题,见此处:
这是代码:
https://codesandbox.io/s/cold-grass-yr6mn?file=/src/container/Board.jsx
问题:
1.)它打印错误的获胜者(用户获胜后游戏改变回合)
2.)当用户获胜时,我想显示“获胜者:X”,而不是“下一个:X”。
为什么失败:
在我的Board.jsx
中,我将以下方法传递给我的 Square.jsx 组件,它会更新棋盘状态和玩家回合:
const updateBoard = (squareIndex) => {
setGameState((prevBoard) => {
// handle previously set value
if (prevBoard[squareIndex] !== "") {
return prevBoard;
}
// otherwise update the board
let updatedBoard = [...prevBoard];
updatedBoard[squareIndex] = playerTurn;
return updatedBoard;
});
// update player turn
setPlayerTurn((turn) => (turn === "X" ? "O" : "X"));
};
在同一个文件中,我有一个 useEffect 来检查 gameState 或玩家何时更新。这种方法决定了获胜者。
// board update events/actions
useEffect(() => {
const isWinner = () => {
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 (
gameState[a] &&
gameState[a] === gameState[b] &&
gameState[a] === gameState[c]
) {
return true;
}
}
return false;
};
if (isWinner()) {
alert(`${playerTurn} is the winner.`);
return;
}
}, [gameState, playerTurn]);
所以它打印错误获胜者的原因是因为一旦有人获胜,它仍然会更新玩家回合,然后会显示失败的玩家。
我的问题
处理更新玩家回合的最佳方法是什么?如果我在我的 useEffect 中设置播放器,我将得到一个无限渲染循环。我可以想出一些破解方法来修复它,比如打印与当前玩家轮到赢家相反的东西。但这似乎并不理想。
任何有关解决此修复的最佳方法的建议都值得赞赏。
谢谢!
解决方案
我试图稍微简化一下逻辑。
链接:https ://codesandbox.io/s/elastic-moon-bcps0?file=/src/container/Board.jsx:0-1829
JS:
import React, { useEffect, useState } from "react";
import Square from "../components/Square/Square";
import styles from "./Board.module.css";
const Board = () => {
const [gameState, setGameState] = useState([]);
const [playerTurn, setPlayerTurn] = useState("X");
// onMount / todo: when user resets board
useEffect(() => {
const initializeGame = () => setGameState(new Array(9).fill(""));
initializeGame();
}, []);
// board update events/actions
useEffect(() => {
let winner = "";
const isWinner = () => {
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 (
gameState[a] &&
gameState[a] === gameState[b] &&
gameState[a] === gameState[c]
) {
winner = gameState[a];
return true;
}
}
return false;
};
if (isWinner()) {
alert(`${winner} is the winner.`);
}
}, [gameState]);
const updateBoard = (squareIndex) => {
if (gameState[squareIndex] !== "") {
return;
}
let updatedBoard = [...gameState];
updatedBoard[squareIndex] = playerTurn;
setGameState(updatedBoard);
// update player turn
setPlayerTurn((turn) => (turn === "X" ? "O" : "X"));
};
return (
<>
<main className={styles.board}>
{gameState.map((cell, position) => (
<Square
boardPosition={position}
displayValue={cell}
updateBoard={updateBoard}
key={position}
/>
))}
</main>
<div>
<p>Next: {playerTurn}</p>
</div>
</>
);
};
export default Board;
推荐阅读
- r - 2 个样品,无需替换原始样品
- spring-boot - 如何将 Spring Security OAuth2 与 Apache Wicket 一起使用?
- javascript - 您可以将 html 直接插入 r shiny 中的 navbarPage 吗?
- python - 即使创建了模块,也找不到 Python 模块
- watchkit - XCode 12.5 无法部署到配对手表的手机 - 设备“(null)”未在您的开发者帐户中注册
- python - 从烧瓶请求中获取模型数据
- vue.js - 按钮元素加加载
- ruby - 是否可以简化此方法?
- node.js - Sequelize onDelete CASCADE 不起作用
- javascript - 使用多维数组构建对象以动态创建列