如何从其他操作的结果中排除操作

时间:2017-01-23 20:47:48

标签: javascript redux react-redux

我有一个redux应用程序,它是一个页面调查。为了更改页面,我有一个NAVIGATION_NEXT_PAGE操作。然后,Reducers处理商店中新页面的创建。我有很多其他动作可以设置问题答案,甚至可以浏览页面。在通过NAVIGATION_NEXT_PAGE显示的每个新页面中,我都有一个用户定义的操作列表,这些操作将在首次显示页面时以及在问题得到解答时执行。

我的问题是如何在每次显示新页面时递归地调度操作,同时仍然将操作逻辑与组件分离。我不想在我的PageContainer中发送操作,因为如果操作要求跳过页面,我根本不希望页面显示。

这是我目前的解决方案:

const actionMiddleware = (store) => (next) => (action) => {
    // Execute post answer actions on the current page.
    switch (action.type) {
        case types.NAVIGATION_NEXT_PAGE:
            for (let postAnswerAction of store.getState().postAnswerActions);
                next(store.dispatch(actionFromPageAction(postAnswerAction)))
            break;
    }
    // Evaluate the action.
    let result = next(action);
    // Execute the preload actions of the new page.
    switch (action.type) {
        case types.NAVIGATION_NEXT_PAGE:
            for (let preLoadAction of store.getState().preLoadActions);
                next(store.dispatch(actionFromPageAction(preLoadAction)))
            break;
    }
    return result;
};

但它引入了奇怪的行为,因为有时反应不会更新我的UI。也许我的中间件会破坏react-redux?

我是在正确的轨道上。什么是从我的中间件调度操作的正确方法?

1 个答案:

答案 0 :(得分:1)

你可以为此制作一个自制的解决方案,但我强烈不建议这样做。下面的这个例子结合了一堆函数,它能够根据给定的动作和商店返回新的动作。 (我没有测试过,但从理论上讲它可能会起作用)

const actionTransformerMiddleware = (...transformers) => store => next => inAction => {
  transformers.map(transformer => transformer(inAction, store))
    .filter(output => !!output) // checking if non null undefined or empty array
    .forEach(actions =>
        // Here alternatively you could store.dispatch these, then the new actions
        // go through the same action transformers, but you won't be able
        // to return an identical action, since that would cause an endless cycle.
        (Array.isArray(actions) ? actions : [actions]).forEach(action => next(action))
    )
}

const whateverActionTransformer = (action, store) => {
  const {postAnswerActions, preLoadActions} = store.getState()
  switch (action.type) {
    case types.NAVIGATION_NEXT_PAGE:
      return (postAnswerActions || []).concat(preLoadAction || [])
  }
}

const myActionMiddleware = actionTransformerMiddleware( 
  whateverActionTransformer,
  // here more of these could come... but maybe they shouldn't?
)

但是我在你发布的例子中看到了一些代码气味(在我的例子中它们也完好无损)。

为什么要在商店中存储操作?你为什么不单独派遣他们?如果这不可行,为什么不用这些动作带来的有效载荷调度动作,让thunk预先形成并组合所有结果并给你一个输出?