如何使用Redux的Immutable.js?

Redux框架正在使用reducer来响应某个操作来更改应用程序状态。

关键要求是reducer不能修改现有的状态对象; 它必须产生一个新的对象。

不好的例子

import { ACTIVATE_LOCATION } from './actions'; export let ui = (state = [], action) => { switch (action.type) { case ACTIVATE_LOCATION: state.activeLocationId = action.id; break; } return state; }; 

很好的例子

 import { ACTIVATE_LOCATION } from './actions'; export let ui = (state = [], action) => { switch (action.type) { case ACTIVATE_LOCATION: state = Object.assign({}, state, { activeLocationId: action.id }); break; } return state; }; 

对于Immutable.js来说,这是一个很好的用例。

以不可变的方式来展示你的好榜样

 import { ACTIVATE_LOCATION } from './actions'; import { Map } from 'immutable'; const initialState = Map({}) export let ui = (state = initialState, action) => { switch (action.type) { case ACTIVATE_LOCATION: return state.set('activeLocationId', action.id); default: return state; } }; 

Immutable.js应该根据需要在每个reducer中使用,例如

 import { ACTIVATE_LOCATION } from './actions'; import Immutable from 'immutable'; export let ui = (state, action) => { switch (action.type) { case ACTIVATE_LOCATION: state = Immutable .fromJS(state) .set('activeLocationId', action.id) .toJS(); break; } return state; }; 

但是,在这个例子中有很多开销:每次调用reducer操作时,都必须将JavaScript对象转换为不可变的实例,对结果对象进行变异并将其转换回JavaScript对象。

更好的方法是使初始状态成为不可变的实例:

 import { ACTIVATE_LOCATION } from './actions'; import Immutable from 'immutable'; let initialState = Immutable.Map([]); export let ui = (state = initialState, action) => { switch (action.type) { case ACTIVATE_LOCATION: state = state.set('activeLocationId', action.id); break; } return state; }; 

这样,您只需要将初始状态转换为Immutable盎司的实例。 然后,每个reducer将它视为Immutable的实例,并将其作为Immutable的实例传递给线程。 现在需要在将值传递给视图上下文之前,将整个状态转换为JavaScript。

如果您在还原器中执行多个状态突变,则可能需要使用.withMutations来考虑批处理突变 。

为了简单起见,我开发了一个redux不可变的库。 它提供了与redux包中的相同名称的函数等价的combineReducers函数,不同之处在于它期望初始状态和所有reducer与Immutable.js对象一起工作。

如果你只是寻找一个简单的方法来更新而不会突变,我维护一个库: https : //github.com/substantial/updeep ,在我看来,这是一个很好的方式来与redux做到这一点。

updeep允许你使用常规的(冻结的)对象层次结构,所以你可以做解构,查看日志和debugging器中的对象等等。它还有一个强大的API,允许批量更新。 对于大数据集来说,它不会像Immutable.js那样高效,因为如果需要的话,它可以克隆对象。

下面是一个例子(但请查阅自述文件中的更多内容):

 import { ACTIVATE_LOCATION } from './actions'; import u from 'updeep'; export let ui = (state = [], action) => { switch (action.type) { case ACTIVATE_LOCATION: state = u({ activeLocation: action.id }, state); break; } return state; }; 

接受的答案不应该是被接受的答案。 你需要使用immutable来初始化状态,而不是像之前提到的使用redux-immutablejs

 const initialState = Immutable.fromJS({}) // or Immutable.Map({}) const store = _createStore(reducers, initialState, compose( applyMiddleware(...middleware), window.devToolsExtension ? window.devToolsExtension() : f => f )); 

比使用redux-immutablejs的combineReducers

额外的提示:使用react-router-redux工作得很好,如果你想添加这个,那么用react-router-reduxreplacereducer:

 import Immutable from 'immutable'; import { UPDATE_LOCATION } from 'react-router-redux'; let initialState; initialState = Immutable.fromJS({ location: undefined }); export default (state = initialState, action) => { if (action.type === UPDATE_LOCATION) { return state.merge({ location: action.payload }); } return state; }; 

只需将其导入到您的根减速器

这也在redux-immutablejs的文档中有说明

看看https://github.com/indexiatech/redux-immutablejs

这几乎是一个combineReducer和一个可选的createReducer符合Redux标准。