Reactjs React、Redux和Immutable

Reactjs React、Redux和Immutable,reactjs,redux,immutable.js,Reactjs,Redux,Immutable.js,与React(以及可选的Redux)一起使用有哪些优点?在Redux中,我可以在我的还原程序中简单地使用rest this返回一个新状态: const initialState = { activeTrackId: '', state: 'stopped', }; export default function (state = initialState, action) { switch (action.type) { case actions.PROCESS_TRACK

与React(以及可选的Redux)一起使用有哪些优点?在Redux中,我可以在我的还原程序中简单地使用rest this返回一个新状态:

const initialState = {
  activeTrackId: '',
  state: 'stopped',
};

export default function (state = initialState, action) {
  switch (action.type) {
    case actions.PROCESS_TRACK_ACTION:
      return {
        ...state,
        activeTrackId: action.state !== 'stopped' ? action.track._id : '',
        state: action.state,
      };
      // ...
我发现它唯一有用的场景是:

shouldComponentUpdate(nextProps) {
  const oldProps = Immutable.fromJS(this.props);
  const newProps = Immutable.fromJS(nextProps);

  return !Immutable.is(oldProps, newProps);
}
据我所知,这甚至可能是误用了它


也许有人能告诉我在React和Redux的上下文中使用Immutable的好处?

如果你小心,不要改变传递的属性,你不必使用Immutable.js

import { Map } from 'immutable';

const initialState = Map({
  core: Map({
    tracker: Map({
      activeTrackId: '',
      state: 'stopped'
    })
  })
});
由于
道具是引用,因此对其进行任何更改都会影响整个应用程序

Immutable.js保证它们不能被修改,但如果您不执行变异,它会对大型应用程序的性能产生影响,但好处是,它可以防止对应用程序状态的任何意外污染

您可以查看深入的解释。

Lee在React Conf 2015上的演讲中介绍了不可变数据的好处和实现。在思考不可变的数据和反应时,我认为它是必不可少的。

除此之外,以下是我对这件事的一些想法

简码 您的状态越复杂,就越难使用文本和扩展运算符来管理它。想象一下,您有几个级别的嵌套状态,而不是扁平的:

const initialState = {
  core: {
    tracker: {
      activeTrackId: '',
      state: 'stopped'
    }
  }
};
虽然仍然可以使用spread操作符,但它开始变得单调乏味

 return {
   ...state,
   core: {
     ...state.core,
     tracker: {
       ...state.core.tracker,
       activeTrackId: action.state !== 'stopped' ? action.track._id : '',
       state: action.state
     }
   }
 };
现在看看Immutable.js的等价物

import { Map } from 'immutable';

const initialState = Map({
  core: Map({
    tracker: Map({
      activeTrackId: '',
      state: 'stopped'
    })
  })
});
然后,我们可以使用持久化API对结构进行深入的更改

return state
  .setIn(
    ['core', 'tracker', 'activeTrackId'],
    action.state !== 'stopped' ? action.track._id : ''
  )
  .setIn(
    ['core', 'tracker', 'state'],
    action.state
  );
值得一提的是,根据状态的形状,拆分和嵌套减缩器可能更有意义

结构共享 当您使用ImmutableJS修改对象时,它会利用使用哈希映射向量实现的事实,尝试在旧对象和修改版本之间共享大部分结构

使用“排列”操作符创建新文字时,将强制复制的数据超过生成新对象所需的数据量

安全 通过保证对象不会发生变异,可以消除一大类bug

对于可变状态,可以将对象引用传递给其他一些代码,这些代码可能会对其进行变异。变异对象不是“错误”,因此不会告诉您对象已更改,也不会有堆栈跟踪,这意味着很难确定变异的来源

无论你的不可变对象去哪里,它们都是安全的

演出 您可以使用不可变的数据结构来做出是否更新组件的更高级决策

shouldComponentUpdate(nextProps) {
  const oldProps = Immutable.fromJS(this.props);
  const newProps = Immutable.fromJS(nextProps);

  return !Immutable.is(oldProps, newProps);
}
尽管这些深度比较可能看起来很昂贵,但它们可以防止您在对象没有更改时需要区分或接触DOM


如果道具本身是不可变的对象,这将更加有效,因为
fromJS
不必重新创建嵌套的级别。

回答得好,丹!这实际上帮助我更了解不可变的。我不确定是使用
Map
,还是
Record
,甚至不知道如何使用这些东西。我有时觉得文档有点混乱。我想知道为什么他们选择使用像
.setIn(['core',tracker',activeTrackId'],value)
这样的格式,而不是
.setIn('core.tracker.activeTrackId',value)
。如果你更喜欢这种类型的符号,有像.PS:甚至更短的库,你可以使用
不可变的.fromJS
并传递任何东西,它将为您设置正确数量的地图和列表。