在调用setState之前,状态会更新

时间:2017-04-20 02:33:16

标签: javascript arrays reactjs

lifeParser是一个被称为处理和更新boardData的方法。问题是当循环仍在处理时,boardData会更新。

lifeParser(){
    var parseArray = this.state.boardData.slice(0);

    for(var i=0;i<30;i++){
        for(var j=0;j<30;j++){
            parseArray[i][j] = 5; // boardData gets updated here before setState is even called
        }
    }
    this.setState({boardData : parseArray});
}

2 个答案:

答案 0 :(得分:2)

这是因为您的boardData是多维的,您无法仅使用slice方法克隆它。像map一样使用它。

var parseArray = this.state.boardData.map(function(arr) {
    return arr.slice();
});

或使用箭头语法

var parseArray = this.state.boardData.map(a => a.slice());

答案 1 :(得分:2)

因为它是嵌套数组。您只是复制第一级(浅层克隆)。内部数组仍然是相同的引用。请考虑以下示例:

var nestedArray = [
 [1, 2, 3],
 [6, 6, 6, 6, 7, 8],
 [0, 3, 5, 6, 5]
];

// This only does a shallow clone
var copy = nestedArray.slice(0);

// When you do this
copy[0][0] = 100;

// `nestedArray` will also be mutated,
// you get 100 here
console.log(nestedArray[0][0]);

在您的情况下,您可以进行深度克隆或仅使用map()之类的内容来获取新的数组:

lifeParser(){
    var parseArray = this.state.boardData.slice(0);

    for (var i = 0; i < 30; i++) {
      parseArray[i] = parseArray[i].map(() => 5);
    }
    this.setState({boardData : parseArray});
}

在此示例中执行深度克隆更加昂贵,因为您需要多一个循环。这里使用map()的好处是您可以同时计算和克隆数据。

在此示例中,您还可以使用两个map()

lifeParser(){
    var parseArray = this.state.boardData.map(innerArray => innerArray.map(() => 5));
    this.setState({boardData : parseArray});
}

// Or this might be more readable:
var parseArray = this.state.boardData.map(innerArray => {
  return innerArray.map(() => 5);
});