仿写 redux 源码(四)

333 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

前情回顾

  • 前面几篇文章,我们首先介绍了如何使用 redux 创建一个数据仓库 store
  • 然后介绍了如何在 react 中使用 redux,并实现了一个 demo
  • 最后我们实现了 redux 中的 createStore 方法
  • 接下来我们将实现 combineReducers 以合并多个 reducer

combineReducers 的使用

  • 为什么需要 combineReducers?
  • 因为我们应用可能比较复杂,这就意味着一个 reducer 函数难以实现所有的状态变更逻辑
  • 很容易想到的解决方案就是,我们应该拆分 reducer 函数为多个 子 reducer,然后交给 redux 中的 combineReducers 帮我们合并多个子 reducer 即可
  • 下面是 combineReducers 的使用
import {
  createStore,  
  combineReducers,
} from "../my-redux";

const countReducer = (state = 100, action) => {
  const { type, payload = 1 } = action;

  switch (type) {
    case "ADD":
      return state + payload;
    default:
      return state;
  }
};

const countReducer2 = (state = { num: 1 }, action) => {
  const { type, payload = 1 } = action;

  switch (type) {
    case "ADD2":
      return { ...state, num: state.num + payload };
    default:
      return state;
  }
};

export const store = createStore(
  // countReducer,

  // 合并多个 reducer
   combineReducers({
     count: countReducer,
     count2: countReducer2,
   }),
);

实现 combineReducers

  • 话不多说,先看代码
/**
 *
 * combineReducers 接收 reducer 的映射关系
 *
 * 返回合并后的 总 reducer
 *
 */
export const combineReducers = (reducerDict) => {
  // 返回是合并之后的总 reducer,所以也会接收 prevState 和 action
  return (prevState = {}, action) => {
    const nextState = {};

    let hasChanged = false;

    for (const key in reducerDict) {
      const reducer = reducerDict[key];
      nextState[key] = reducer(prevState[key], action);

      hasChanged = hasChanged || nextState[key] !== prevState[key];
    }

    hasChanged =
      hasChanged ||
      Object.keys(nextState).length !== Object.keys(prevState).length;

    return hasChanged ? nextState : prevState;
  };
};
  • combineReducers 的实现也很简单
  • 它接受的所有 子reducer 的映射关系对象
  • 因此通过 for in 循环这个映射关系对象,即可拿到每个 子reducer
  • 然后执行每个 子reducer,将每个 子reducer 执行后产生的新的状态,按照之前接受的 reducer 的映射关系对象存放即可
  • 还有一个比较细节的点是,combineReducers 方法中,通过 hasChanged 来标识是否有状态变更
    • 若有,则返回新的状态即可
    • 若没有,则返回原始状态
    • 这样做是为了遵守不可变数据的规则,数据发生变更则重新生成一个状态即可,外部使用时也比较方便的去判断,是否产生的数据变更

小结

  • 本文介绍了 redux 中 combineReducers 方法的实现,下篇文章将实现 applyMiddleware 的实现

  • 今天的分享就到这里了,欢迎大家在评论区里面进行讨论 👏

  • 如果觉得文章写的不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰