如何在执行reducer之前为所有操作添加一组参数?

时间:2017-01-28 06:58:27

标签: redux

我正在寻找一种方法,在输入(根)减速器时为每个动作添加一些参数。

快速举例,让我假设我有userState,其中包含当前已登录的用户,甚至可能处于某种子状态。

  rootState
     |
     +-------------------------------------+
     |                                     |
 userState                            +----+-----+
     |                                |          |
 +---+-----------+                   ...     salesState
 |               |
...    currentlySignedInUserState

为了在另一个reducer(例如salesReducer)中执行一个动作,我需要拥有当前已登录的用户,这个用户不是很容易获得(处于兄弟状态或更糟糕状态)所以我必须拦截在根状态中的操作,从currentlySignedInUserState读取userState,将用户添加到操作有效负载,并使用更改的有效负载重新发出操作。

case SALES_ACTIONS.ADD_SALE:
    return Object.assign({}, state, {
        let payload = Object.assign({}, action.payload, {
            userName: state.user.signedIn.name
        });
        sales: salesReducer(state.sales, {
            type: SALES_ACTION.ADD_SALE,
            payload
        });
});

这变得一团糟,并阻止我使用combineReducers,因为我必须在我自己制作的根减速器中转发每一个动作。

所以我提出了这样的想法:只需将用户添加到每个操作进入根减速器,然后只是combineReducers

这是一种被接受的方法,如果是这样,有没有办法扩展combineReducers以便它需要额外的有效载荷参数(我在考虑redux-reuse,但我不确定是否会做我想到的事情。)

如果没有,我的替代方案是什么?

1 个答案:

答案 0 :(得分:3)

您可以使用从状态获取userName的简单middleware,并将其作为meta数据添加到所有操作,除非signedIn。您可以添加其他条件,例如应跳过的特定操作。 我更喜欢将其他数据添加为meta,而不是有效负载。 我已经提出了两种方法来增强行动。

(未经测试的)代码:

const middleware = ({ getState }) => next => action => {
  const state = getState();

  if(!state.user.signedIn) { // if not signed in skip
        return next(action);
  }

  const userName = state.user.signedIn.name;

  /** add userName using assign **/
  const meta = Object.assign({}, action.meta, { userName });
  const newAction = Object.assign({}, action, { meta });
  /**********************/

  /** or add userName using object spread **/
  const newAction = { 
    ...action, 
    meta: { ...action.meta, username } 
  };
  /**********************/

  next(newAction);
};