在React状态下更改2D数组

时间:2018-09-18 16:53:27

标签: javascript reactjs ecmascript-6

我的初始状态如下:

constructor(props) {
    super(props);

    this.state = this.getInitialState();

    this.setSqValue = this.setSqValue.bind(this);
}

getInitialState() {
    return {
        allSq: new Array(3).fill(new Array(3).fill(null))
    };
}

然后在像setSqValue这样的方法中(通过单击按钮调用),当我为一个单元格分配新值时,奇怪的是,所有其他在第一维上具有任意位置而在第二维上具有相同位置的单元格都将采用该值!

第二个问题是,在我未调用任何setState的情况下,状态已更改!

setSqValue(i, j) {
    console.log(i, j);

    let {allSq} = this.state;

    let value = 'foo';

    console.log('before', allSq);

    allSq[i][j] = value;

    console.log('after', allSq);

//    this.setState({allSq});
}

控制台中的输出是这样:

the output in the console

您可以看到前后值相同(为什么?!)。

React开发人员工具中的状态:

the state in the react developer tool

2 个答案:

答案 0 :(得分:1)

在JavaScript中,数组是一种特殊的对象,如果将对象传递给fill(),则每次使用相同的对象。您应该改用map(),这将创建数组的副本。

allSq: Array(3).fill().map(() => Array(3).fill(null))

要防止更改状态,可以使用Object.freeze()方法:

allSq: Object.freeze(Array(3).fill().map(() => Object.freeze(Array(3).fill(null))))

这样,行allSq[i][j] = value;将以太抛出错误(在strict mode中)或无声地失败(在严格模式之外)。

答案 1 :(得分:1)

在chrome开发工具中,只有打开对象后才对其进行评估。将鼠标悬停在右侧的小图标上,您会看到Object below was evaluated just now.。尝试在其中放置debugger,我有一种感觉,您会发现以前的allSq在其中没有foo。似乎一切正常,您只是在看错误的东西而已。

另外,正如另一个用户所说,.fill使用引用而不是值,因此使用.map