Redux提供了非常强大的数据流管理功能,是一个可预测的状态容器,解决数据在 React 应用中的流动方式及过程
1.原理
Redux 的中间件提供的是位于 action 被发起之后,到达 reducer 之前的扩展点,这种机制可以让我们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。
原redux的数据流:view -> action -> reducer -> store
加上中间件后变成了: view -> action -> middleware -> reducer -> store
2.接口
createStore函数接收参数为(reducer, [initState], enhancer)
import {createStore, applyMiddleware} from 'redux';
import thunkMiddleware from 'redux-thunk';
import rootReducer from '../reducers';
import defaultState from './defaultState';
export default function configureStore() {
let store = createStore(
rootReducer,
defaultState,
applyMiddleware(
thunkMiddleware
)
);
return store;
}
enhancer是一个组合 StoreCreator 的高阶函数, 返回的是一个新的强化过的 StoreCreator,再执行StoreCreator就能得到一个加强版的 store。
例子中enhancer即为applyMiddleware,从下面的源码可知,applyMiddleware 改写了 store 的 dispatch 方法,新的 dispatch 即是被所传入的中间件包装过的。
applyMiddleware 的源码:
export default function applyMiddleware(...middlewares) {
return createStore => (...args) => {
const store = createStore(...args)
let dispatch = () => {
throw new Error(
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// 将不同的 middlewares 一层一层包裹到原生的 dispatch 之上
// compose 将 chain 中的所有函数组装成一个新的函数,即新的 dispatch
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
3.解读
例子1:
//一个啥都不干的中间件:
const doNothingMidddleware = (dispatch, getState) => next => action => next(action)
参数 dispatch 和 getState,分别代表着 Redux Store 上的两个同名函。然后中间件doNothingMidddleware 返回的函数接受一个 next 类型的参数,这个 next 是一个函数,如果调用了它,就代表着这个中间件完成了自己的职能,并将对 action 控制权交予下一个中间件。最后以 action 为参数的函数对传入的 action 对象进行处理,在这个地方可以进行操作,比如:
- 调动dispatch派发一个新 action 对象
- 调用 getState 获得当前 Redux Store 上的状态
- 调用 next 告诉 Redux 当前中间件工作完毕,让 Redux 调用下一个中间件
- 访问 action 对象 action 上的所有数据
在具有上面这些功能后,一个中间件就足够获取 Store 上的所有信息,也具有足够能力可用之数据的流转。
例子2:
最出名的中间件 redux-thunk,可以处理异步操作 :
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
redux-thunk 中间件的功能很简单。首先检查参数 action 的类型,如果是函数的话,就执行这个 action 函数,并把 dispatch, getState, extraArgument 作为参数传递进去,否则就调用 next 让下一个中间件继续处理 action 。
另外还有一些中间件如redux-logger(打印日志)、redux-promise(处理异步操作,但是返回Promise对象)、redux-saga等