将 redux 与 immutable-js 一起使用时 - 你会在你的选择器上调用 toJS() 吗?还是在渲染函数中使用 .get('prop') ?

When using redux with immutable-js - do you call toJS() on your selector? Or do you use .get('prop') in the render function?

现在我正在使用 reselect 创建我的选择器以从商店中提取数据并通过 connect 将其传递给 props。 为了简单起见,我的选择器的结果总是一个 JS 对象(在选择器的末尾调用 toJS()),像这样:

const selector = state => state.get('data').toJS();

现在我正在尝试提高一些性能,我意识到 shouldComponentUpdate 由于我从选择器返回的方式,浅层比较失去了不变性的优势。

另一方面,在我的 html 中使用 .get('prop') 似乎非常烦人:

<div>{this.props.data.get('prop')}</div>

特别是如果我将一个简单的 JS 对象传递给一个可变的子组件,就像这样:

<ChildComponent totalItems={10} />

然后访问props时不一致(有的可变,有的不可变)。

我想创建一个辅助 unwrap 函数,像这样:

const unwrap = obj => obj && obj.toJS ? obj.toJS() : obj;

但我不太喜欢这个解决方案。我真的不喜欢这些方法中的任何一种。

您使用什么来获得干净的代码和性能?

要将 props 传递给组件,请将键下的所有数据收集为不可变。

<MyComponent propsKey={Immutable.fromJS({someData: {key: "value"}})} />

要利用 Immutable 的优势,您应该避免使用 toJS()。这是非常昂贵的,你不能用它来使用有用的不可变函数。在达到 "value" 之前,您应该使用 Immutable.get()。一开始它很烦人,但您会及时看到它的实用性和易用性。 (使用 getIn() 获取内部键可能比链获取函数更不烦人)。通过这种方式,您的代码可以更高效地工作,并且您不需要使用 unwrap 函数,在您的组件中,您可以保证 this.props.propsKey 下的数据始终不可变。

您应该将展示组件包装在一个简单的高阶组件中,该组件在传递给它的任何 Immutable.js 对象道具上调用 toJS()

这将为您提供最佳平衡,既可以保持 Immutable.js 的性能优势,又可以防止您的容器组件重新渲染过多,并保持您的展示组件无依赖性,因此可以轻松重用和可测试。

Redux 文档有很好的选择best practises for using Immutable.js, in particular, when not to use .toJS(), why your presentational components should be kept pure and how a "toJS" higher-order component might be defined and used

一年半后回到我的问题并给出我自己的答案:

如果可能,总是传递不可变对象。如果它不是不可变的,就按原样传递它。

我认为性能比代码的美观重要得多。

如果一个值是不可变的或可变的,我会按原样传递它,如果不需要,我永远不会调用 toJS。如果可变值未存储在 redux 存储中,我也不会用 fromJS 包装它们。

我只需要知道在子组件内部,有些 props 是不可变的,有些则不是 - 这实际上很简单,因为几乎总是一个复杂的对象是不可变的。