Redux 中间件
中间件
上文中 我们介绍了 Redux 的基本用法 但是我们在 Reducer 中都是同步代码
承接上文计数器的 🌰 如果我们想在 Reducer 中将用定时器将每个操作延迟 1s
代码如下
// 创建Reducer 用于管理 View 派发过来的 Action
const reducer = (store = initStore, action: IAction) => {
switch (action.type) {
case ACTION_TYPE.ADD_COUNTER: {
let { count } = store;
setTimeout(() => {
count = count + action.payload;
});
return { ...store, count };
}
case ACTION_TYPE.SUB_COUNTER:
return { ...store, count: store.count - action.payload };
default:
return store;
}
};我们用定时器来模拟 真实场景下的一些 api 操作
上文中 我们提到 Redux 有三大原则 它们都只为做一件事
让 Redux 的每一步操作都变得可预测
但是我们无法确定 我们在 Reducer 中书写的异步操作会在什么时候触发 从而改变 Store
这将会是 Redux 的 Store 变得难以预测
我们再来回顾一下 Redux 中的数据流
UI —————> action(plain)—————> reducer —————> state —————> UI
其实 action 是一个原始 js 对象(plain object)且 reducer 是一个纯函数
所以 如果想要实现异步操作 这些具有副作用的行为时 就需要在 action 和 reducer 中间再架设一层处理异步逻辑的中间层
这就是中间件 加入中间件后 Redux 数据流如下
UI —————> action(side function) —————> middleware —————> action(plain) —————> reducer —————> state —————> UI
既然 知道了数据流 我们就可以手动来实现一个中间层
我们可以 dispatch(中间件函数) 然后在中间件函数中处理数据 最后 return 一个干净的纯函数
举个 🌰 以下是我新建的一个 middleware.ts
wait 是我写的一个工具函数 用来暂停程序 模拟异步请求
然后在组件中 我们就可以用 addCounterAsync 代替 addCounter 即可
当然 社区上早已有了很多处理异步 action 的库
下面主要介绍两种中间件 redux-thunk 和 redux-saga 然后安利一下rematch
redux-thunk
改造后的代码如下 省去无关代码
其他地方正常使用即可
通过 thunk 我们可以在 dispatch 前拦截 action
然后进行网络请求等异步操作 最后让 action 带上我们需要的数据 变成原始的 action(plain object) 再 dispatch 出去
但是这种方法的缺点也很明显 就是将异步请求的操作和 actionCreator 杂糅在了一起
对于每一个需要异步操作的 action 我们都需要在 actionCreator 中写一个对应的函数 这样会使 actionCreator 变的越来越大 不易于管理
所以对应的 又有一种中间件 saga
redux-saga
在 saga 中 side effect 都移到了 saga.js 文件中 不再和 actionCreator 杂糅在一起
saga 的体系庞大完整 但是也相对复杂 还是用一个计数器的 🌰 来康康 saga 的使用
首先是我们的 store 文件
然后是 saga 文件
rematch
关于 rematch 的介绍 可以参考传送门
rematch 可以简化传统的 redux 使我们免去写 actionType actionCreator
我们用 rematch 来实现计数器的 🌰
首先是 store
如果我们有多个 store 我们就可以在一个文件中统一管理我们的 store
init 函数会帮助我们创建一个 store 同时它会帮助我们自动开启 redux devtools 调试工具
业务组件
Last updated
Was this helpful?