一起养成写作习惯!这是我参与「掘金日新计划 · 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 的实现
-
今天的分享就到这里了,欢迎大家在评论区里面进行讨论 👏
-
如果觉得文章写的不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰