• Reducers 的 State 管理
    • 简单的 Reducer

    Reducers 的 State 管理

    这个简单的想法证明是非常强大的。 使用Redux,你可以将一系列事件重播到reducer中,从而获得新的应用程序状态。

    Redux应用程序中的Reducer不应该改变state,而是返回一个副本,并且无副作用。 这鼓励你把你的应用程序想象成从一系列事件中“计算”的UI。

    让我们来看看一个简单的计数器reducer。

    简单的 Reducer

    app/reducer/counter-reducer.ts

    1. import { INCREMENT_COUNTER, DECREMENT_COUNTER } from '../actions/counter-actions';
    2. export default function counter(state = 0, action) {
    3. switch (action.type) {
    4. case INCREMENT_COUNTER:
    5. return state + 1;
    6. case DECREMENT_COUNTER:
    7. return state - 1;
    8. default:
    9. return state;
    10. }
    11. }

    我们可以看到,我们正在传递一个初始状态和一个动作。为了处理每个动作,我们设置了一个switch语句。而不是每个reducer需要显式订阅分发器,每个动作都会传递到每个reducer,它处理它感兴趣的动作,然后返回新状态到下一个reducer。

    Reducers 应无副作用。这意味着他们不应该修改自己范围之外的东西。他们应该简单地计算下一个应用程序状态作为reducer参数的纯函数。

    出于这个原因,诸如更新数据库中的记录,生成id等的副作用引起操作应该在应用中的其他地方处理,例如在动作创建者中,使用中间件例如 ‘Epics’ from redux-observable 或 ngrx/effects。

    创建reducer时的另一个考虑因素是确保它们是不可变的,而不是修改应用程序的状态。如果您改变应用程序状态,它可能会导致意外的行为。有几种方法可以帮助维护reducer的不变性。一种方法是使用ES6的新功能,如Object.assign或数组的展开运算符。

    1. function immutableObjectReducer(state = { someValue: 'value'} , action) {
    2. switch(action.payload) {
    3. case SOME_ACTION:
    4. return Object.assign({}, state, { someValue: action.payload.value });
    5. default:
    6. return state;
    7. }
    8. }
    9. function immutableArrayReducer(state = [1,2,3], action) {
    10. switch(action.payload) {
    11. case ADD_ITEM:
    12. return [...state,action.payload.value]
    13. default:
    14. return state;
    15. }
    16. }

    但是,当处理复杂或深层嵌套的对象时,可能很难使用此语法在应用程序中维护不变性。这种情况下像Immutable.js这样的库可以提供帮助。