繁体   English   中英

React:有效更新数组状态

[英]React: Efficient updating of array state

React的基本思想之一是状态更改应始终且仅通过this.setState(...)发生,而不是手动操作状态。 但是对于状态是一个深层数组的情况,因此是一个对象常量数组(实际上是一些JSON数据),更新该State确实非常昂贵。 如果我只想更新这样一个数组的一个元素,则代码将类似于以下内容。

handleChange(index, newElement){
    var newStateArray = _.cloneDeep(this.state.myArray);
    newStateArray[index] = newElement;
    this.setState({myArray: newStateArray });
}

我知道标准解决方案将使用浅表复制,但实际上仅是浅表阵列的副本。 就我而言,事实并非如此,因此浅表复制会在某种意义上“错误”,因为它将改变状态。 那么,应该如何处理呢? 我可以使用一个浅表副本,它可以工作,但是感觉很脏,在技术上是错误的。

编辑 :或澄清一下:如果我只使用浅拷贝的东西并确保告诉React手动更新,会发生什么不好的事情吗?

编辑 :哦,这似乎已经解决了自己。 浅复制无法像我想的那样工作。 我是JS新手,请原谅。 以供参考:

var a = [{a:1}, {b:2}, {c:3}]
var b = a.slice();
b[0] = 42; // I thought this would change a, but it doesn't!

只要您将所有对象都视为不可变的(即,如果您需要更改属性,请先进行浅表复制),就不会出错。 例如:

起始状态:

var A = {
    foo: 3,
    bar: 7
};
var B = {
    baz: 11,
    boop: 5
};
var C = {
    myA: A,
    myB: B
};

假设我们要更改C-> myB-> boop。 A中没有任何变化,因此我们不需要复制,但是我们确实需要同时复制B和C:

var newB = {
    baz: B.baz,
    boop: 1000000 // we have to update this in B, so we need a new B
};
var newC = {
    myA: C.myA,
    myB: newB    // we have to update this in C, so we need a new C
};

(显然,您将使用浅表复制来制作每个部分的副本,然后在顶部分配更改;为清楚起见,我只是手动写出副本)

当我们将newC提交为新状态时,它将仅共享未更改的部分(在本例中为A),这很好,因为它们始终被视为不可变的对象。

概括地说,当您更改任何属性时,将需要对持有该属性的对象以及对象的父对象及其父对象的父对象等进行浅表复制,直至返回根节点。 您也可以以完全相同的方式考虑数组。 为此,它们只是具有编号属性的对象。

如果您在所有进行更改的地方都遵循这些规则,则浅数组副本将可以正常工作。 这适用于您具有状态历史记录的任何情况,而不仅仅是reactjs。

参见React的不变性助手

handleChange(index, newElement){
    var newStateArray = update(this.state.myArray, {
        [index]: {b: {$set: newElement.target.value} }
    });
    this.setState({myArray: newStateArray });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM