使用 immutable.js 的 react shouldComponentUpdate 的最佳实现是啥

Posted

技术标签:

【中文标题】使用 immutable.js 的 react shouldComponentUpdate 的最佳实现是啥【英文标题】:What is the best implememtation of react shouldComponentUpdate with immutable.js使用 immutable.js 的 react shouldComponentUpdate 的最佳实现是什么 【发布时间】:2016-08-06 10:08:42 【问题描述】:

我是ImmutableJS 的新手。我的应用实现了大型 Redux Store 和多个 react 组件。

如果我错了,请纠正我:

我了解 Immutable 的好处是保护 Flux Store 并避免组件上不必要的 vDom 渲染获得不变的 props。 要从 ImmutableJS 更好的渲染性能中受益,必须实现 shouldComponentUpdate()

这个功能的最佳实现是什么?

我已经找到了它的几个实现,都使用了 shallowEqual() 并进行了一些修改:

Facebook 为 React 实现了 shallowEqual,我想还有更多。 Jurassix 提供了实现shallowEqualImmutable 的an implementation。它是来自 Facebook 的函数,只是 is() 函数被 ImmutableJS 提供的函数替换。第一个等式也不同。 Dan 对 different shalllowEqual function 执行相同的操作,它实现了前两个实现的部分内容。

有人知道我应该使用哪种实现方式吗?或者没有并实施特定的shouldComponentUpdate()?在这一点上我有点不知所措

非常感谢您的帮助!!

【问题讨论】:

你看过 PureRenderMixin 吗? facebook.github.io/react/docs/pure-render-mixin.html 这也是浅比较,但使用 ImmutableJs 就足够了。 是的,PureRenderMixin 实际上是从 Facebook 调用 shallowEqual。这是我提到的第一点。 “足够了”是什么意思? 【参考方案1】:

我了解 Immutable 的好处是保护 Flux Store 并避免组件上不必要的 vDom 渲染获得不变的 props。

这与 Immutable 无关(如果您指的是库)。例如,您可以在 Redux 中使用普通对象和数组,但由于 Redux 要求您永远不要改变它们,因此在大多数情况下您会获得几乎相同的好处。因此,Immutable 库可以提供更好的 API 来更新不可变的东西,但如果您不改变普通对象或数组,则不需要它来进行性能优化。

为了从 ImmutableJS 更好的渲染性能中受益,必须实现 shouldComponentUpdate()。

同样,与 ImmutableJS 没有真正的关系,但是是的,要从 props 的不变性中受益,您需要实现 shouldComponentUpdate()。但是,如果您使用 Redux,您可能已经使用了 React Redux 包中的 connect(),它在大多数情况下为您实现了 shouldComponentUpdate()。所以你真的不需要为任何 connect() ed 组件手动编写它。

有人知道我应该使用哪种实现方式吗?或者没有并实现特定的 shouldComponentUpdate()?在这一点上我有点不知所措

如果您没有性能问题,也不要使用。在大多数情况下,React 本身的性能相当好,在它上面添加一个 connect() 会添加一个很好的默认实现 shouldComponentUpdate()

对于不是connect()ed 但仍经常更新的组件,我建议您使用react-addons-shallow-comparePureRenderMixin 在内部使用它,但由于现代 React API 中并没有真正使用 mixin,因此单独的函数可能更方便。

如果你想要对Immutable.is 的特殊支持,你确实可以使用shallowEqualImmutable 之类的东西。它更好地理解不可变集合,因为它认为相同值的列表是相同的。此时,您最好针对您的应用分析不同的实现,因为具体情况可能会因您的用例而异。

不要过早优化,在解决之前确保这是一个实际问题。

【讨论】:

您还拥有recompose 的实现(pureonlyUpdateForKeysonlyUpdateForPropTypes),它们允许您使用高阶组件,以便您可以将代码保存在无状态功能组件语法。 @Dan,非常感谢您提供的详细信息。我知道shouldComponentUpdate()ImmutableJS 是两个完全不同的东西。它正在考虑这两个概念,这让我不知何故。但我认为你的回答很有帮助。你让我意识到 shouldComponentUpdate() 应该使用 react-addons-shallow-compare 用于可变道具,shallowEqualImmutable 用于来自 ImmutableJS 库的不可变。 @Dan,: 你在这一点上是绝对正确的:“此时你最好针对你的应用程序分析不同的实现,因为具体情况可能会因你的用例而异”。 Redux-Form 迫使我实现不需要使用 ImmutableJS 的良好 shouldComponentUpdate() 技术上你仍然可以使用 react-addons-shallow-compare ,即使是 ImmutableJS 道具。很多人都这样!在某些情况下它不会纾困,但它已经足够好了,如果需要,您可以随时走得更远。【参考方案2】:

我也在使用大型的 Redux Store,发现使用 Immutable.js 会使状态的访问变得复杂,例如,nested2.getIn(['a', 'b', 'd']) vs嵌套2.abd;我真正需要的是确保我不会改变减速器中的状态,并且仍然能够在 shouldComponentUpdate() 方法中使用 === 检查相等性。

我创建了https://github.com/engineforce/ImmutableAssign 来满足我的要求。它是一个轻量级的不可变助手,它支持不可变性并允许您继续使用 POJO(Plain Old javascript Object),因此我们的 React 组件可以像往常一样读取状态,例如,

return newState.a.b.d === oldState.a.b.d; 

例子,

var iassign = require("immutable-assign");

var o1 =  a:  b:  c: [[ d: 11, e: 12 ], [ d: 21, e: 22 ]], c2:  , b2:  , a2:  ;

//
// Calling iassign() to push new item to o1.a.b.c[1]
//
var o2 = iassign(
  o1,
  function (o)  return o.a.b.c[1]; ,  // get property to be updated 
  function (c)                         // update select property
    c.push(101); 
    return c; 
  
);


// o2.a.b.c[1][1] === 101
// o1 is not modified

// o2 !== o1
// o2.a !== o1.a
// o2.a.b !== o1.a.b
// o2.a.b.c !== o1.a.b.c
// o2.a.b.c[1] !== o1.a.b.c[1]

// o2.a2 === o1.a2
// o2.a.b2 === o1.a.b2
// o2.a.b.c2 === o1.a.b.c2
// o2.a.b.c[0] === o1.a.b.c[0]
// o2.a.b.c[0][0] === o1.a.b.c[0][0]
// o2.a.b.c[1][0] === o1.a.b.c[1][0]

【讨论】:

以上是关于使用 immutable.js 的 react shouldComponentUpdate 的最佳实现是啥的主要内容,如果未能解决你的问题,请参考以下文章

使用 immutable.js 的 react shouldComponentUpdate 的最佳实现是啥

React+Immutable.js的心路历程

Immutable.js 与 React Typescript 结合

将 Flux 存储中的 Immutable.js 映射与内部 React 组件状态合并

是否可以在 React-Redux 应用程序中使用 Immutable.js 来比较 shouldComponentUpdate 中的道具?

大话immutable.js