【问题标题】:Copying two-dimensional array from state in React.js从 React.js 中的状态复制二维数组
【发布时间】:2019-02-18 19:43:16
【问题描述】:

我正在尝试为模型 Conway's Game of Life 构建一个小型反应应用程序。我设置了一个二维数组来跟踪 10×10 网格中每个单元格的状态。

我正在尝试将此数组存储在 State 中。在游戏的每个“滴答”中,我想制作一个数组副本,评估每个单元格,可能给它一个新值,然后将副本分配回状态。我基于官方React Tutorial 使用这种精确方法:

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.blahx = 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] = //... 就足以以某种方式修改状态。

这是我在 Board 组件的构造函数中设置初始数组的代码:

  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);
  }

我查看了here,但根据点击更新方块没有任何问题(我的代码的那部分工作正常)。各种 SO 帖子和面对面的疑难解答提出了三种不同的复制策略,它们都会产生相同的问题。我也看了here

我对 React 很陌生,一般来说对 JS 不是很熟练,显然我对 State 没有很好的处理。以下是我的问题:

  1. 如何以不引用状态的方式复制状态/状态的一部分/状态中的数据?我希望能够在不更改状态的情况下更改这些新数据(直到我准备好)。
  2. 为什么上面使用的方法不能正常工作? slice() 的文档向我保证,我得到的是副本而不是参考。

提前致谢!我很困惑。

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    spread operator 仅对值进行 副本。这意味着如果您在其中有任何嵌套值,它们将被引用而不是复制。例如:

    const a = { field: { innerField: 'test' } };
    const b = { ...a } // b ===  { field: { innerField: 'test' } } SAME field as a
    

    要复制嵌套数组,您应该使用深复制方法,例如 Lodash's cloneDeepRamda's clone

    例如,使用 Lodash 的 cloneDeep:

    const newSquares = _.cloneDeep(this.state.squares);
    

    【讨论】:

    • 感谢您的回复。我在研究中也遇到了 Lodash 的 cloneDeep。两个问题:1.为什么slice()不起作用?文档说它返回值的副本,而不是参考。 2.在普通的JS中真的没有简单/容易的方法来创建深拷贝吗?确实令人难以置信,您需要导入一些外部库来执行看似基本的任务。
    • slice()... 相同 - 浅拷贝。不幸的是,我不知道这样做的任何内置方式。
    猜你喜欢
    • 1970-01-01
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多