Redux中间件解析
1. Redux的工作原理
redux对于我们进行全局的状态管理是非常有用的,我们可以省去很多力气去管理组件间的状态传递等等
-
redux中的核心api和作用
redux解决的真正问题是React组件间的状态共享和状态管理问题,通过以上的6个核心api我们便能管理复杂的状态,并能监听和追溯状态的改动,redux的工作机制如下
当我们要去改变状态的时候,我们会dispatch一个action(一个普通的js对象),我们最终的状态改变是在reducer中进行的,reducer会根据原来的state和action来产生一个新的state,这样store中的状态改变了之后又会将数据展示到页面上,完成了我们的状态管理。
2. redux中间件
中间件是一个非常好用的东西,我们回顾我们上面讲到的流程,如果我们要进行一些其它的事情,比如对于每一次状态改变都打印日志,或者说我们可以进行异步的action。怎么做呢,首先action是一个对象,我们肯定不好在这里做拓展,然后reducer又是一个纯函数,我们也不方便在这里做有side effect的事情,所以我们唯一可以做处理的就是dispacth。redux中间件的主要思想就是会重写之前的dispatch,然后会让这个dispatch做我们想要做的事。我们使用中间件的时候都会这样使用
import { createStore, applyMiddleware } from 'redux';
import reducers from './reducers';
const middlewares = applyMiddleware(middleware1, middleware2);
const store = createStore(reducers, middlewares);
上面有一个applyMiddleware
方法,我们看一下这个方法的源代码
export default function applyMiddleware(...middlewares) {
return createStore => (...args) => {
const store = createStore(...args)
let dispatch = () => {
throw new Error(
`Dispatching while constructing your middleware is not allowed. ` +
`Other middleware would not be applied to this dispatch.`
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
// 参数一,传入原始的getState和dispatch
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// 参数二: 传入中间件链上的上一个dispatch,最开始的传入原始的dispatch
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
解读一下:以中间件thunk
为例
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => (next) => (action) => {
// 这边可以让我们dispatch一个函数,我们可以在这个函数里面执行副作用的事情
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
// 使用上一个dispatch来调用我们传进去的action
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
发现一个中间件的形式是这样的
({ dispatch, getState }) => (next) => (action) => {}
有三个参数,前两个参数都是在applyMiddleware
中调用的,最后一个参数就是action,也就是我们调用dispatch的时候传入的。顺便提一下注入第二个参数的时候引入的compose函数,源码如下
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
// 链式调用中间件,可以看成一个洋葱模型
return funcs.reduce(function(a, b) {
return function (...args) {
return a(b(...args))
}
})
}
其实就是一个reduce函数,也就是将上一个函数传递给下一个函数使用,也就实现了我们之前所说的第二个参数就是上一个中间件执行后的dispatch。这个可以参考下MDN上的reduce中提到的这个功能性管道函数
以上就是redux和中间件的主要思想了,精妙的很