Redux - 理解 combineReducers

Posted samwangdd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redux - 理解 combineReducers相关的知识,希望对你有一定的参考价值。

最近在项目中使用 redux 时遇到一个问题:使用多个 reducer 管理状态(如 ruducerA,reducerB),当通过 action 更新数据时,当前的 reducerA 数据更新成功,但另一个 reducerB 数据被初始化。

这个行为让我非常迷惑,排查了很久, 一度找不到下手点。代码如下:

APP.js

const rootReducer = combineReducers({
  RudecerA,
  RudecerB,
});
 
const store = createStore(
    rootReducer
);
 
 
export default function App(props) {
  return (
    <Provider store={store}>
        <Router {...props} />
    </Provider>
  );
}

reducerB.js

export function ReducerB(
  state = initState,
  action,
  ) {
    switch (action.type) {
      case UPDATE_RECORD_DATA:
        return { ...state, recordData: action.payload };
       case DELETE_RECORD_DATA:
         return { ...state, recordData: initRecordData };
        default:
          return initState;
   }
}

解决办法

后来在官方文档看到关于 combineReducer 的介绍及注意点:

所有未匹配到的 action,必须把它接收到的第一个参数也就是那个 state 原封不动返回。

看到这里突然好像找到了希望,因为我在 reducerB 中默认返回的是 initState。于是我试着将 initState 改为 state,问题竟然真的解决了!

但是为什么 combineReducer 要求默认返回 state 呢?

追问溯源

首先我们使用 combineRuducer 的目的是通过切片方式来管理 state,它最终会合并所有的 state 并返回。

export function combineReducers<S>(
  reducers: ReducersMapObject<S, any>
): Reducer<CombinedState<S>>

通过查看源码,发现 combineRudecer 主要做了以下几件事:

  • 过滤不合法的 reducer
  • 遍历所有合法的 reducer ,并得到新的 state
  • 判断 state 是否更新,如果更新就返回新值,否则反之。
  • 合并所有 state,并返回。

总结

因为在平时开发中使用 switch case 时,都会给 default 赋值为 initState,防止程序出错。

而在 combineReducer 中每当发起 action 时,当前 reducer 会走到 case 中,返回期望的结果,但另外的reducer 没有命中条件,返回的就是初始值。

有时候因为惯性思维而写下一些难以排查的 bug,非常浪费精力,在使用这些库时,应该多理解其中原理,让自己少走弯路。

以上是关于Redux - 理解 combineReducers的主要内容,如果未能解决你的问题,请参考以下文章

Redux 的 combineReducers 和 TypeScript

combineReducers 破坏 Redux 状态并破坏多个 ImmutableJs 减速器

Redux 中的CombineReducer的函数详解

Redux 中 combineReducers实现原理

关于redux和react-redux使用combinereducers之后的问题

4 react 简书 引入 redux 的 combineReducers 对 redux 数据进行管理