reactjs - 当子组件运行 setState 时,useEffect 不会更新
我正在用 React 制作一个井字游戏,并且我把父组件的 setState 函数传给了子组件,用来改变棋盘。
之后,我在父组件中放置了一个 useEffect(useEffect(()=> ... , [board]))来在这个状态改变时执行某个动作。但是当我在子组件中使用 setState 时,它没有任何反应。下面的 console.log 显示为 true,这可能是 useEffect 没有更新的原因。
function handleClick(_, i:number) {
setBoard(prevBoard => {
const newBoard = board
newBoard[i] = dictIconToValue[icon] as typeof prevBoard[0]
console.log(newBoard == prevBoard)
return newBoard
})
...
}
答案#1
下面的 console.log 显示为 true,这可能是 useEffect 没有更新的原因。
没错。React 中的 state 是不可变的。当你调用 setBoard 时,React 会使用 Object.is 检查(类似于 ===)将旧的 state 与新的 state 进行比较。如果它们相同,看起来就像什么都没改变,所以 React 会跳过重新渲染。React 不会检查 state 内部的属性是否改变,因为那可能开销很大。
相反,请确保你创建一个新状态,而不是修改旧的状态:
setBoard(prevBoard => {
const newBoard = [...board]; // <--- creating a shallow copy
newBoard[i] = dictIconToValue[icon] as typeof prevBoard[0]
return newBoard
})
答案#2
就 React 而言,状态实际上并没有被更新,因为它仍然是相同的对象引用。你是在修改状态,而不是创建一个新的实例。
这不会复制数组,它只是将一个新变量指向同一个引用:
const newBoard = board
因此,对 newBoard 所做的任何更改都是直接在状态实例上进行的(修改它)。相反,应创建一个包含现有数组元素副本的新数组(这些元素本身可能是引用,但这通常是一个边缘情况,在这里不应成为问题):
const newBoard = [...board]
在这种情况下,newBoard 完全是一个新的对象引用,所以当它被设置为状态时,React 会将其视为已更新的状态。
