我正在使用 React 开发一个井字游戏。
游戏单元的点击处理程序如下所示:
function onClick(row, cell) {
if (!state.game[row][cell]) {
state.game[row][cell] = state.player === 1 ? 1 : 2;
state.player = state.player === 1 ? 2 : 1;
setState({ ...state });
}
}
我基本上是改变旧状态并通过将其属性复制到新对象中(以创建新引用)来将其作为新状态重用。
尽管如此,对 state.game
数组的引用保持不变,所以我想知道这样做是否合适,或者它是否容易出错,以及是否应该始终深度克隆 React 中的状态。>
答案 0 :(得分:1)
此代码可能会导致错误。可能是这个顶级组件没有显示错误,因为它唯一关心的事情有一个新的引用。但是如果你将状态的一部分作为 props 传递给其他组件,它们可能会被突变抛弃。
因此,您应该在要更改的每个级别创建一个副本。例如:
function onClick(row, cell) {
if(!state.game[row][cell]) {
const newRow = [...state.game[row]];
newRow[cell] = state.player === 1 ? 1 : 2;
const newGame = [...state.game];
newGame[row] = newRow;
setState({
...state,
player: state.player === 1 ? 2 : 1,
game: newGame,
})
}
}
答案 1 :(得分:1)
改变状态可能会导致 React 看不到更改并且不会重新渲染您的组件的问题。
如果您的状态很复杂,那么使用 lodash.cloneDeep()
制作副本会更容易,然后对副本进行变异但保持之前的状态不变。
import _cloneDeep from 'lodash/cloneDeep';
...
function onClick(row, cell) {
if (!state.game[row][cell]) {
const newState = _cloneDeep(state);
newState.game[row][cell] = state.player === 1 ? 1 : 2;
newState.player = state.player === 1 ? 2 : 1;
setState(newState);
}
}