Redux框架正在使用reducers更改应用状态以响应操作。
关键要求是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的一个很好的用例。
答案 0 :(得分:48)
以Immutable
为例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;
}
};
答案 1 :(得分:25)
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对象转换为Immutable实例,改变生成的对象并将其转换回JavaScript对象。
更好的方法是让初始状态为Immutable:
的实例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。
如果您在reducer中执行多个状态突变,则可能需要使用.withMutations
来考虑batching mutations。
为了简单起见,我开发了一个redux-immutable库。它提供的combineReducers
函数等同于redux包中同名函数的功能,除了它期望初始状态和所有reducers与Immutable.js对象一起使用。
答案 2 :(得分:8)
如果你只是在寻找一种简单的方法来进行无变异的更新,我会维护一个库:https://github.com/substantial/updeep,在我看来,这是用redux
做到这一点的好方法。
updeep
允许您使用常规(冻结)对象层次结构,因此您可以进行解构,查看日志中的对象和调试器等。它还具有允许批量更新的强大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;
};
答案 3 :(得分:5)
接受的答案不应该是接受的答案。 你需要使用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-redux替换reducer:
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
的文档中说明了这一点答案 4 :(得分:2)
查看https://github.com/indexiatech/redux-immutablejs
它几乎是一个combineReducer
和一个符合Redux标准的可选createReducer
。