yon*_*oni 4 arrays reactjs react-hooks use-state
有一个带有方块的板,它们的值依赖于一个数组,它是用useState钩子处理的。每次点击都应该将值提高一,但不幸的是,它会提高两倍(除了第一次点击)。
我的问题是:
(1) 为什么会发生这种情况,(2) 如何避免这种情况,以及,一般来说,(3) 是否有更好的方法来使用钩子处理这样的数组。
let emptyBoard = Array.from({ length: parseInt(props.rows, 10) }, () =>
new Array(parseInt(props.columns, 10)).fill(0)
);
const [squaresValues, setSquaresValue] = useState(emptyBoard);
function onClick(id) {
const [rowIndex, cellIndex] = id;
console.log("the " + id + " square was clicked");
setSquaresValue(prevValues => {
let newBoard = [...prevValues];
console.log("before: " + newBoard[rowIndex][cellIndex]);
newBoard[rowIndex][cellIndex] = newBoard[rowIndex][cellIndex] + 1;
console.log("after: " + newBoard[rowIndex][cellIndex]);
return newBoard;
}
);
}
Run Code Online (Sandbox Code Playgroud)
日志:
the 3,0 square was clicked
before: 0
after: 1
the 3,0 square was clicked
before: 1
after: 2
before: 2
after: 3
Run Code Online (Sandbox Code Playgroud)
可以看出,从第二次单击开始,每次单击该值都会提高两倍。
你仍在改变状态,如果你有纯组件,那么它们在改变时不会重新渲染。如果您有纯组件,则使用 JSON.parse 进行完整状态复制是一个坏主意,因为所有内容都将被重新渲染。
let newBoard = [...prevValues];
newBoard[rowIndex] = [...newBoard[rowIndex]];
newBoard[rowIndex][cellIndex] =
newBoard[rowIndex][cellIndex] + 1;
Run Code Online (Sandbox Code Playgroud)
正如 Udaya Prakash 在上面的评论中提到的,它被调用两次以确保你的 setState 是独立的和幂等的。所以,如果我理解正确的话,它被调用两次并不是一个错误,但你的值第二次被改变才是。
以下是 Dan Abramov 对同一 GitHub 问题的评论:
预计 setState 更新程序将在开发中以严格模式运行两次。这有助于确保代码不依赖于它们运行一次(如果异步渲染被中止并更改重新启动,则不会出现这种情况)。如果您的 setState 更新程序是纯函数(它们应该是),那么这不应该影响您的应用程序的逻辑。
我们可以通过深复制prevValues而不是使用扩展运算符进行浅复制来修复它。JSON.parse(JSON.stringify(...)您可能已经知道,有多种方法可以深度复制您的对象,我们现在可以使用,您可以从这里替换为您最喜欢的类型
setSquaresValue(prevValues => {
let newBoard = JSON.parse(JSON.stringify(prevValues)); // <<< this
console.log("before: " + newBoard[rowIndex][cellIndex]);
newBoard[rowIndex][cellIndex] = newBoard[rowIndex][cellIndex] + 1;
console.log("after: " + newBoard[rowIndex][cellIndex]);
return newBoard;
});
Run Code Online (Sandbox Code Playgroud)
如果你想玩一下,我已经在codesandbox中模拟了它。
| 归档时间: |
|
| 查看次数: |
4827 次 |
| 最近记录: |