Redux - 有没有办法在reducer中访问存储树?

时间:2015-12-22 16:01:21

标签: redux

就我而言,我有一家商店,如:

{
  aa: {...},
  bb: cc  // the result of computing with aa
}

我需要同时更新aabb,但bb需要获得aa的最新计算。

这是一些代码(React.js):

onClick(e) {
  const { dispatch, aa, bb } = this.props;

  dispatch(updateAa());
  dispatch(updateBb(aa)); // can not get the latest computation of aa, it is the last computation..
}

那么,这是否意味着我需要在aa的缩减器中获取bb

我怎么能这样做?

希望有所帮助!,谢谢!

7 个答案:

答案 0 :(得分:33)

请勿使用combineReducers.

示例

替换此代码

export const a = combineReducers({
  app,
  posts,
  intl,
  products,
  pos,
  cats,
});

export default (state = {}, action) => {
  return {
    app: app(state.app, action, state),
    posts: posts(state.posts, action, state),
    intl: intl(state.intl, action, state),
    products: products(state.products, action, state),
    pos: pos(state.pos, action, state),
    cats: cats(state.cats, action, state),
  };
};

reducer就像

const reducer = (state = initialState, action, root) => {....}

答案 1 :(得分:14)

有几种可能性,但鉴于代码含糊不清,很难说哪种方法最好。

  • 理想情况下,your store should be normalized,意味着每个数据仅在一个地方可用。然后,您将在读取商店后计算派生数据,例如当您使用指南中描述的selector pattern将商店的状态映射到您可能认为的物化视图时以props的形式发送给您的组件。在此工作流程中,aabb将分别由选择器函数生成,而不是存储在该商店中。
  • 您可以保留在aa之外更新bbcombineReducers的缩减器,以便它可以看到整个状态,而不是缩小到aa的状态, bb
  • 您可以将计算代码分解为可由updateAaupdateBb调用的帮助程序,并在每个操作中传递足够的信息以进行计算。
  • 您可以在分派之前计算更新,以便该操作包含正确的值。

答案 2 :(得分:8)

正如David L. Walsh所说,可能你应该以更合理的方式构建减速器。

如果您仍然认为自己需要它,可以使用thunk中间件。 (https://github.com/gaearon/redux-thunk) Redux Thunk中间件允许您编写返回函数而不是动作的动作创建者。

Redux Thunk为您提供了一种读取Redux商店当前状态的方法。除了dispatch之外,它还将getState作为第二个参数传递给你从thunk action creator返回的函数。

export function action() {
    return function(dispatch, getState){
        const state = getState()
        dispatch({
            type: "ACTION_WITH_SOME_PART_OF_STATE,
            some_part_of_state: state.some_part
        })   
    }
}

答案 3 :(得分:5)

问问自己是否正确构建了减速器。如果a和b不是彼此独立的,为什么它们是单独的减速器?我会尝试将它们合并为一个减速器。

答案 4 :(得分:0)

根据谢赫·阿卜杜勒·瓦希德(Sheikh Abdul Wahid)的回答,我必须进行以下修改才能使其与historyconnected-react-router一起使用:

()之后的connectRouter(history)

import { connectRouter } from 'connected-react-router'

const createRootReducer = (history) => {
  return (state = {}, action) => {
    return {
      ...reducers,
      router: connectRouter(history)(),
      ...rest of reducers
    }
  }
}

答案 5 :(得分:0)

如果这是您的常用用例,则可以尝试编写自己的函数,以根据需要official Redux documentation推荐根据需求组合减速器:


切片缩减器之间共享数据

类似地,如果sliceReducerA恰好需要sliceReducerB的状态切片中的某些数据来处理特定操作,或者sliceReducerB恰好需要整个状态作为参数,那么CombineReducers不会自行处理。这可以通过编写一个自定义函数来解决,该函数知道在这些特定情况下将所需数据作为附加参数传递,例如:

text.text = "";

我强烈建议您阅读this documentation page,其中还有其他一些建议在减速器之间共享数据,甚至可以将function combinedReducer(state, action) { switch (action.type) { case 'A_TYPICAL_ACTION': { return { a: sliceReducerA(state.a, action), b: sliceReducerB(state.b, action) } } case 'SOME_SPECIAL_ACTION': { return { // specifically pass state.b as an additional argument a: sliceReducerA(state.a, action, state.b), b: sliceReducerB(state.b, action) } } case 'ANOTHER_SPECIAL_ACTION': { return { a: sliceReducerA(state.a, action), // specifically pass the entire state as an additional argument b: sliceReducerB(state.b, action, state) } } default: return state } } 用于简单操作,并针对特殊情况使用其他定制减速器。

希望这些选项对您有所帮助!

答案 6 :(得分:-1)

如果某个reducer需要来自另一个reducer的某些数据,那么一个简单的解决方案是将它们合并到单个reducer中。 就我而言,我需要来自另一个化简器的一些数据,并且很难管理它们,因此最终将它们合并。