我正在尝试构建一个小型React应用程序来建模Conway的生活游戏。我已经设置了一个二维阵列,以在10 x 10网格中跟踪每个单元格的状态。
我正在尝试将此数组存储在该州。在游戏的每个" tick"中,我想制作一个数组的副本,评估每个单元格,可能给它一个新的值,然后将副本分配回状态。我是根据官方的React教程来使用这种确切方法的官方React教程:
handleClick(i) {
//Make a copy from state
const squares = this.state.squares.slice();
//Make some changes to it
squares[i] = 'X';
//Set state to the new value
this.setState({squares: squares});
}
我最初的方法是如上示例中使用slice()
。通过调试,我发现这不起作用。即使我使用各种方法来复制它不应该对其进行更改,即使状态正在改变。(我知道,如果我说var x = this.state.blah
和x = 5
我已更改状态,因为blah
是对它的参考)
这是我的代码:
doTick = () => {
console.log("doin a tick");
console.log(this.state.squares);
//None of these approaches works
//Three different copy strategies all fail
//const newSquares = Object.assign({}, this.state.squares);
//const newSquares = [...this.state.squares];
//const newSquares = this.state.squares.slice();
const newSquares = this.state.squares.slice();
const origSquares = [...this.state.squares];
//Iterating over the array
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
newSquares[i][j] = evaluateCell(origSquares[i][j], this.countLiveNeighbors(i, j, origSquares));
//evaluateCell(origSquares[i][j], this.countLiveNeighborsAndLog(i, j, origSquares));
}
}
//this.setState({
//squares: newSquares
//});
}
即使评论了setState()
调用,只要将newSquares[i][j] = //...
的分配就足以修改状态。
这是我在板组件的构造函数中设置初始数组的代码:
constructor(props) {
super(props);
var array = new Array(10);
for (var i = 0; i < 10; i++) {
array[i] = new Array(10).fill(false);
}
this.state = {
squares: array
};
console.log(this.state.squares);
}
我在这里看一看,但是我在基于点击更新正方形时毫无困难(我的代码的那一部分正常工作)。各种如此的帖子和面对面的疑难解答者提出了三种不同的副本策略,这些策略都会产生相同的问题。我也在这里看一看。
我对JS的反应非常新手,而且在JS上不是很熟练,显然我对状态没有很好的处理。这是我的问题:
- 如何以状态的状态/数据的副本/一部分来制作副本不是对状态的方式?我希望能够在不改变状态的情况下更改此新数据(直到我准备就绪)。
- 为什么上面使用的方法无法正常工作?slice()的文档向我保证,我要获得副本而不是参考。
预先感谢!我很困惑。
传播运算符仅对值的 shallow 副本。这意味着,如果您的嵌套值中有任何嵌套值,则将被引用而不是复制。例如:
const a = { field: { innerField: 'test' } };
const b = { ...a } // b === { field: { innerField: 'test' } } SAME field as a
要复制一个嵌套数组,您应该使用深层复制方法,例如Lodash的Clonedeep或Ramda的克隆
例如,与lodash的克隆eep:
const newSquares = _.cloneDeep(this.state.squares);