在没有 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] 时,您正在复制一个引用数组,这确实是一个新数组(通过索引修改直接子数组,如 012 未反映)但填充了相同的对象引用,因此 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

当使用对象而不是值时,nextPropsthis.props.value 将被视为不同的引用(除非我们执行深度比较)并触发重新渲染,这在规模上可能非常昂贵.

¹除非你模拟自己的不变性,否则我相信 Immutable.js 更好

你不是在复制角色,因此如果你的组件之一作为道具(如果有的话)不能利用纯渲染优化(覆盖 shouldComponentUpdate 并检测道具何时实际更改)。

但是因为不用immutablejs也可以复制角色,所以除了打字多了(犯错的机会多)外,没有任何有效的区别。这本身就是一个巨大的缺点,会降低您的工作效率。