在React中使用不可变状态有什么缺点?

Thi*_*man 23 javascript immutability reactjs immutable.js

我已经使用有状态存储以"正常"方式构建了我的第一个React应用程序,现在我正在研究使用Este starterkit中使用的不可变全局状态.

  • 所有商店的状态保存在一个不可变的数据结构中
  • 组件没有状态,但基于商店getter函数访问render()中的数据
  • 商店也是无状态的,但使用游标改变其域的全局应用程序状态.
  • 顶级应用程序组件侦听状态更改,并重新呈现整个组件树.
  • 组件被实现为"纯粹"意味着他们使用shouldComponentUpdate来有效地计算出它们在重新渲染中可以被跳过.

它以几种方式简化了应用程序结构:

  • 组件不会侦听存储,也不会将存储数据复制到本地状态.他们只是在每个渲染上抓住他们的商店状态.
  • 全局状态始终是整个应用程序的快照,使调试和添加撤消功能更容易.
  • 全局状态似乎简化了同构渲染.

我只读了关于在React中使用不可变数据的积极的事情,建议避免组件中的状态,所以我想知道是否有任何缺点.我想一定有,因为否则我不明白为什么它不推荐,因为构建应用程序做出反应的方式.

不变性对我来说是新的,所以如果我在一个复杂的真实应用程序中开始使用这种方法,我应该注意一些警告吗?

我能想到的唯一一件小事是在Este使用它时使用forceUpdate(),因为我已经读过它是一个同步函数.例如,Morearty似乎将更新推迟到下一个动画帧以便批量处理它们,但我认为这是一个实现细节/优化,而不是一些继承的不可变单态方法的缺点.

haz*_*ous 14

  1. 文档.SO中一些投票最多的问题/咆哮是关于更新嵌套列表项的琐碎事情,因为文档更倾向于熟悉函数式编程的观众,这使得其他人不太容易接近.
  2. 将模型层次结构知识与组件分离并非易事.我讨厌this.state.getIn("[parent, child, index]")在一个组件中做一个,因为它增加了模型更改破坏组件代码的可能性.这可以通过可扩展性(更多关于下面的内容)或通过帮助方法来预防,但是你肯定会失去普通JS成员的简单性.
  3. 我面临的一个重大挑战是能够序列化和反序列化状态.fromJS方法支持自定义恢复,但它们是皮塔饼,需要仔细测试和维护.
  4. 记录类型被称为嵌套的弱化严重阻碍.这很令人遗憾,因为它允许更容易(相对而言)可扩展性,但仅鼓励单级层次结构.您无法轻松地从JSON创建嵌套记录.这使得很难将它们与常规的不可变fromJS用法混合,除非你使用上面提到的皮塔复兴.并且我提到了多么悲伤,因为Records将模型属性公开为第一类成员,确保模型完整性和默认值.
  5. 然后有可扩展性.尝试在不可变数据模型周围添加帮助程序以抽象组件中的模型层次结构依赖关系,并且您需要进行明显的跨栏竞赛.反序列化成为一场激烈的离婚之战.你需要乱搞复活,如果记录混合他们将会犯规,等等.更简单的可扩展性机制将大大有助于使我的组件代码更清晰.
  6. 没有记录的最佳实践.尽管这与#1正确相关,但我仍然应该提到缺乏良好的文档会阻止人们选择最佳的做事方式.我不确定是否应该选择使用更新程序,或者使用forEach或setIn(等等)来更新不可变结构.这些方法不会相互交叉引用,以便让您知道有哪些替代方案.

  • 大多数这些参数似乎是反对使用Immutable.js的论据.您可以编写正常的Javascript,并且仍然注意不要改变任何对象,从而获得实用的不变性. (2认同)

Mic*_*ley 6

通过道具传递数据的一个优点是,您可以利用shouldComponentUpdate更高效的更新.如果您假设数据始终来自父级(例如通过道具),则可以有效地防止组件树的大部分必须重新渲染.不可变值使得这非常好,因为您可以shouldComponentUpdate在组件层次结构中相对较高地引用相等性检查.

我在React中使用不可变数据时发现的唯一另一个缺点是React开发人员工具不能很好地与它们一起工作(它们向您展示了不可变值的底层数据结构,而不是JS友好的值).