9.1.2 使用中间件
您可以在百度里搜索“深入浅出React和Redux 艾草文学(www.321553.xyz)”查找最新章节!
9.1.2 使用中间件
使用中间件有两种方法,两种方法都离不开Redux提供的applyMiddleware函数。
第一种方法是用Redux提供的applyMiddleware来包装createStore产生一个新的创建Store的函数,以使用redux-thunk中间件为例,代码如下:
import {createStore, applyMiddleware} from 'redux';
import thunkMiddleware from 'redux-thunk'
const configureStore = applyMiddleware(thunkMiddleware)(createStore);
const store = configureStore(reducer, initialState);
为了使用thunkMiddleware,将thunkMiddlware作为参数传递给applyMiddleware,产生了一个新的函数,新产生的函数实际上是一个Store Enhancer(很快就会介绍到Store Enhancer,在这里只需要理解Store Enhancer是一中能够增强Store功能的函数就行),这个Store Enhancer函数又将Redux的createStore作为参数,产生了一个加强版的创造store的函数,习惯上将这个增强的createStore命名为configureStore,利用configure-Store创造的Store将具有thunkMiddleware中间件的功能。
对于没有使用其他Store Enhancer的场景,上述的方法还可以一用,但是实际中应用基本都会需要其他Store Enhancer的辅助,比如便于Redux开发的Redux Devtools增强器,在有其他增强器出现的情况下,再用这种方法就显得很不方便,所以上面介绍的第一种方法现在很少使用了,取而代之的是第二种方法。
第二种方法也就是把applyMiddleware的结果当做Store Enhancer,和其他Enhancer混合之后作为createStore参数传入。
以同时使用redux-thunk和Redux Devtools增强器为例,代码如下:
import {createStore, applyMiddleware, compose} from 'redux';
import thunkMiddleware from 'redux-thunk'
const win = window;
const storeEnhancers = compose(
applyMiddleware(...middlewares),
(win && win.devToolsExtension) ? win.devToolsExtension() : f => f
);
const store = createStore(reducer, storeEnhancers);
可以看到,applyMiddlware函数的执行结果,和其他的Store Enhancer处于同级的位置,Redux提供了一个compose函数,可以把多个Store Enhancer串接起来成为一个函数,因为createStore只能接受一个Store Enhancer的参数。
createStore最多可以接受三个参数,第一个参数是reducer,第二个参数如果是对象,就会被认为是创建Store时的初始状态,这样第三个参数如果存在就是增强器。但如果第二个参数是函数类型,那就认为没有初始状态,直接把第三个参数当做增强器处理。
值得一提的是,使用这种方法应用中间件的时候,一定要把applyMiddlware的结果作为compose的第一个参数,也就是要放在所有其他Store Enhancer之前应用。这是因为增强器的顺序也就是它们处理action对象的顺序,applyMiddleware配合redux-thunk或者其他中间件要处理异步action对象。如果不是优先把他们摆在前面的话,异步action对象在被它们处理之前就会被其他Store Enhancer处理,无法理解异步对象的增强器就会出错。
在上面的例子中,如果把applyMiddleware放在win.devToolsExtension()后面的话,遇到异步对象就无法工作,在浏览器Console中可以看到如下错误信息:
Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
这就是因为action对象在被redux-thunk处理之前就被Redux Devtools捕获了,而Redux Devtools无法处理函数类型的异步action对象。 深入浅出React和Redux