反应:有效更新阵列状态
React: Efficient updating of array state
React 的一个基本思想是,状态更改应该始终且只能通过 this.setState(...)
发生,而不是手动操作状态。但是对于状态是深度数组的情况,因此对象文字数组(实际上是一些 JSON 数据),更新该状态变得非常昂贵。如果我只想更新此类数组的一个元素,则代码将如下所示。
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 });
}
- 事件和状态
- 获取选择框的状态
- 相位器状态未捕获参考错误
- 如何更改reactjs中外部/独立组件的状态或属性
- 如何使用密码检测网络中的状态连接
- Ember.js-接口状态应该存储在哪里
- 混合 ui-sref 和 $state.go 在 Angular ui-router 中进行状态转换
- 在Angular 2中布线期间保持零部件处于活动状态
- 在mvc应用程序中,在回发时保留最初隐藏的文本框的隐藏或可见状态
- XMLHttpRequest未返回值-状态202
- 使用javascript反复检查用户在facebook上的登录状态
- 如何使bxslider仅在移动视图中处于活动状态
- 获取ASP.NET Ajax Timer状态
- React redux初始化功能,无论状态变化如何
- 无法在现有状态转换期间更新-未使用任何非法的setState()
- 悬停下拉菜单即使在鼠标移出后也保持活动状态
- 从组件状态的数组中删除元素
- iOS 中的按钮触摸状态
- 使用AngularJS中的UI路由器将状态重定向到默认子状态
- 反应:有效更新阵列状态