[英]Trouble with React not updating state (hooks)
I have a small memory game that I am building to learn React.我有一个 memory 小游戏,我正在构建它来学习 React。 The idea is that you click a tile, it is shuffled, and you try to pick one you haven't already selected.
这个想法是,您单击一个图块,它会被打乱,然后您尝试选择一个您尚未选择的图块。 The problem is I can't seem to get my internal state for which tiles have previously been seen to update.
问题是我似乎无法获取我的内部 state,之前已经看到它更新了磁贴。
Here is my component:这是我的组件:
const Gameboard = (props) => {
const [tiles, setTiles] = useState([]);
const [currentScore, setCurrentScore] = useState(0);
const [highScore, setHighScore] = useState(0);
const [previouslySeen, setPreviouslySeen] = useState([]);
const handleClick = (evt) => {
const tile = evt.target;
if (!previouslySeen.includes(tile)) {
setCurrentScore(current => current + 1);
props.setCurrentScore(current => current + 1);
setPreviouslySeen([...previouslySeen, tile]);
} else {
alert("Game over, thanks for playing!");
if (currentScore > highScore) {
setHighScore(currentScore);
props.setHighScore(currentScore);
}
setCurrentScore(0);
props.setCurrentScore(0);
setPreviouslySeen([]);
}
};
const generateTiles = (tileCount) => {
return [...Array(tileCount).keys()].map((n) => {
return <Tile key={n} number={n} handleClick={handleClick} />;
});
};
const shuffleTiles = (tiles) => {
let tilesCopy = [...tiles];
for (let i = tilesCopy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * i);
const temp = tilesCopy[i];
tilesCopy[i] = tilesCopy[j];
tilesCopy[j] = temp;
}
return tilesCopy;
};
useEffect(() => {
const initialTiles = generateTiles(props.tileCount);
setTiles(shuffleTiles(initialTiles));
}, []);
useEffect(() => {
setTiles((oldTiles) => {
const newTiles = shuffleTiles(oldTiles);
return newTiles;
});
}, [currentScore, highScore]);
return <div className="Gameboard">{tiles}</div>;
};
The handleClick
method gets passed into the individual Tile
components and is just called with onClick
. handleClick
方法被传递到各个Tile
组件中,并且仅使用onClick
进行调用。 The handleClick method is what is giving me trouble, it seems as if it doesn't ever update
previouslySeen`, and I have similar problems with setting the high score in the parent component so that it is reflected in the UI. handleClick method is what is giving me trouble, it seems as if it doesn't ever update
过 previouslySeen`,我在父组件中设置高分以使其反映在 UI 中时遇到类似的问题。 How are you supposed to handle updates like this in React?你应该如何在 React 中处理这样的更新?
Try this:试试这个:
const handleClick = (evt) => {
const tile = evt.target;
if (!previouslySeen.includes(tile)) {
setCurrentScore(current => current + 1);
props.setCurrentScore(current => current + 1);
// Change the following line:
setPreviouslySeen(previousState => [...previousState, tile]);
} else {
Also, you're getting setCurrentScore, setHighScore
from parent props and from declaring states:此外,您将从父属性和声明状态中获取
setCurrentScore, setHighScore
:
const [currentScore, setCurrentScore] = useState(0);
const [highScore, setHighScore] = useState(0);
So essentially you're keeping two separate currentScore
and highScore
states - one in the Gameboard
component, and one in its parent.所以基本上你保持两个独立的
currentScore
和highScore
状态 - 一个在Gameboard
组件中,一个在它的父组件中。 It's best to delete these state variables and setters from Gameboard
and get them directly from parent props.最好从
Gameboard
中删除这state个变量和setter,直接从parent props中获取。
It turned out that it was because I was storing JSX elements directly in state. Removing that and instead just storing the tile value (plain JS strings) fixed the issue where state wasn't being correctly updated.事实证明,这是因为我将 JSX 元素直接存储在 state 中。删除它并仅存储平铺值(纯 JS 字符串)解决了 state 未正确更新的问题。 Quite the gotcha!
真是陷阱!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.