在没有 Immutable 的情况下深度更新 React 状态(数组),有什么缺点吗?
Deeply updating React state (array) without Immutable, any disadvantages?
我知道使用 Immutable 是深度更新 React 状态的好方法,但我想知道这种方法是否有任何我没有发现的缺点:
假设 this.state.members
的形状为 Array<MemberType>
,其中 MemberType
为 { userId: String, role: String }
。
如果用户更改用户角色,则执行以下方法:
changeMemberRole = (userId, event, key, value) => {
const memberIndex = _findIndex(this.state.members,
(member) => member.userId === userId);
if (memberIndex >= 0) {
const newMembers = [...this.state.members];
newMembers[memberIndex].role = value;
this.setState({ members: newMembers });
}
};
除了可能更简洁的语法外,用 Immutable 的 setIn
替换它是否有任何优势?
来自 setIn
文档:
Returns a new Map having set value at this keyPath. If any keys in keyPath do not exist, a new immutable Map will be created at that key.
这可能不是您要查找的内容,因为您可能不想插入具有给定角色的新成员(如果该成员不存在)。这归结为您是否能够控制函数中传递的 userId
参数并预先验证它是否存在。
这个解决方案很好。如果需要,您可以将其替换为 update。
使用与不使用 Immutable.js
的区别当然是不变性¹ :)
当您声明 const newMembers = [...this.state.members]
时,您正在复制一个引用数组,这确实是一个新数组(通过索引修改直接子数组,如 0
、1
、2
未反映)但填充了相同的对象引用,因此 inner/deep 更改被共享。这称为浅拷贝。
newMembers
不是这样 new
因此,对任何 newMembers
元素的任何更改也会在相应的 this.state.members
元素中进行。这对你的例子来说很好,到目前为止没有真正的优势。
那么,为什么是不变性?
它的真正好处不容易在小片段中观察到,因为它更多的是关于心态。摘自 Immutable.js homepage:
Much of what makes application development difficult is tracking
mutation and maintaining state. Developing with immutable data
encourages you to think differently about how data flows through your
application.
不可变性带来了许多函数范式的好处,例如避免副作用或竞争条件,因为您将变量视为值而不是对象,从而更容易理解它们的范围和生命周期,从而 minimizing bugs。
React 的一个具体优势是 safely check for state changes in shouldComponentUpdate
而在变异时:
// assume this.props.value is { foo: 'bar' }
// assume nextProps.value is { foo: 'bar' },
// but this reference is different to this.props.value
this.props.value !== nextProps.value; // true
当使用对象而不是值时,nextProps
和 this.props.value
将被视为不同的引用(除非我们执行深度比较)并触发重新渲染,这在规模上可能非常昂贵.
¹除非你模拟自己的不变性,否则我相信 Immutable.js
更好
你不是在复制角色,因此如果你的组件之一作为道具(如果有的话)不能利用纯渲染优化(覆盖 shouldComponentUpdate 并检测道具何时实际更改)。
但是因为不用immutablejs也可以复制角色,所以除了打字多了(犯错的机会多)外,没有任何有效的区别。这本身就是一个巨大的缺点,会降低您的工作效率。
我知道使用 Immutable 是深度更新 React 状态的好方法,但我想知道这种方法是否有任何我没有发现的缺点:
假设 this.state.members
的形状为 Array<MemberType>
,其中 MemberType
为 { userId: String, role: String }
。
如果用户更改用户角色,则执行以下方法:
changeMemberRole = (userId, event, key, value) => {
const memberIndex = _findIndex(this.state.members,
(member) => member.userId === userId);
if (memberIndex >= 0) {
const newMembers = [...this.state.members];
newMembers[memberIndex].role = value;
this.setState({ members: newMembers });
}
};
除了可能更简洁的语法外,用 Immutable 的 setIn
替换它是否有任何优势?
来自 setIn
文档:
Returns a new Map having set value at this keyPath. If any keys in keyPath do not exist, a new immutable Map will be created at that key.
这可能不是您要查找的内容,因为您可能不想插入具有给定角色的新成员(如果该成员不存在)。这归结为您是否能够控制函数中传递的 userId
参数并预先验证它是否存在。
这个解决方案很好。如果需要,您可以将其替换为 update。
使用与不使用 Immutable.js
的区别当然是不变性¹ :)
当您声明 const newMembers = [...this.state.members]
时,您正在复制一个引用数组,这确实是一个新数组(通过索引修改直接子数组,如 0
、1
、2
未反映)但填充了相同的对象引用,因此 inner/deep 更改被共享。这称为浅拷贝。
newMembers
不是这样 new
因此,对任何 newMembers
元素的任何更改也会在相应的 this.state.members
元素中进行。这对你的例子来说很好,到目前为止没有真正的优势。
那么,为什么是不变性?
它的真正好处不容易在小片段中观察到,因为它更多的是关于心态。摘自 Immutable.js homepage:
Much of what makes application development difficult is tracking mutation and maintaining state. Developing with immutable data encourages you to think differently about how data flows through your application.
不可变性带来了许多函数范式的好处,例如避免副作用或竞争条件,因为您将变量视为值而不是对象,从而更容易理解它们的范围和生命周期,从而 minimizing bugs。
React 的一个具体优势是 safely check for state changes in shouldComponentUpdate
而在变异时:
// assume this.props.value is { foo: 'bar' }
// assume nextProps.value is { foo: 'bar' },
// but this reference is different to this.props.value
this.props.value !== nextProps.value; // true
当使用对象而不是值时,nextProps
和 this.props.value
将被视为不同的引用(除非我们执行深度比较)并触发重新渲染,这在规模上可能非常昂贵.
¹除非你模拟自己的不变性,否则我相信 Immutable.js
更好
你不是在复制角色,因此如果你的组件之一作为道具(如果有的话)不能利用纯渲染优化(覆盖 shouldComponentUpdate 并检测道具何时实际更改)。
但是因为不用immutablejs也可以复制角色,所以除了打字多了(犯错的机会多)外,没有任何有效的区别。这本身就是一个巨大的缺点,会降低您的工作效率。