我知道使用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
替换它有什么好处,除了可能更简洁的语法之外?
答案 0 :(得分:3)
使用与否Immutable.js
之间的区别当然是不变性¹:)
当您声明const newMembers = [...this.state.members]
您正在复制引用数组时,这确实是一个新数组(通过索引修改直接子项,如0
,1
,{{1}没有反映)但是填充了相同的对象引用,因此共享内部/深层更改。这称为浅拷贝。
2
不是 new 因此,对任何newMembers
元素的任何更改也会在相应的newMembers
元素中进行。这对你的例子来说很好,到目前为止还没有真正的优势。
在小片段中不容易观察到它的真正好处,因为它更多地是关于心态。取自Immutable.js homepage:
许多使应用程序开发变得困难的因素是跟踪 突变和维持状态。使用不可变数据进行开发 鼓励您以不同的方式思考数据如何流经您的 应用
不变性带来了许多功能范例的好处,例如避免副作用或竞争条件,因为您将变量视为值而不是对象,从而更容易理解其范围和生命周期,从而minimizing bugs。
当发生变异时,反应的一个特定优势是safely check for state changes in shouldComponentUpdate
:
this.state.members
使用对象而不是值// 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
时,将被视为不同的引用(除非我们执行深度比较)并触发重新渲染,这在规模上可能非常昂贵。< / p>
¹除非你模仿自己的不变性,否则我相信this.props.value
更好
答案 1 :(得分:0)
你没有复制角色,因此如果你的一个组件扮演道具(如果有的话)不能利用纯渲染优化(覆盖shouldComponentUpdate并检测道具实际改变的时候)。
但是既然你可以在没有immutablejs的情况下制作角色的副本,除了你必须输入更多(因此有更多机会犯错误)之外没有任何有效的区别。这本身就是一个降低生产力的巨大缺点。
答案 2 :(得分:-1)
来自setIn
文档:
返回在此keyPath处具有设定值的新Map。如果keyPath中的任何键不存在,将在该键上创建一个新的不可变映射。
这可能不是您正在寻找的内容,因为您可能不希望插入具有给定角色的新成员(如果它尚不存在)。这取决于您是否能够控制函数中传递的userId
参数并验证它是否存在。
这个解决方案很好。如果您愿意,可以将其替换为update。