本文主要对于redux官方文档中的async示例结合一些源码做出一些理解。
此示例通过<select>
选择相应的value(reactjs与frontend)作为selectedReddit,向Reddit API请求相应的json数据,获取数据后渲染到列表中。主要采用了react-thunk作为middleware来实现。
首先,再来看一下createStore
的定义,第三个参数applyMiddleware
相应的中间件,这里thunkMiddleware
主要是用来异步控制的,后面会再次讲解
|
|
我们来看一下createStore
的源码,是如何处理middleware的,省去了一些无用的代码,即applyMiddleware(createStore)(reducer, initialState)
|
|
再看一眼applyMiddleware
的代码,如果对=>
有些茫然,可以先查阅ES6中箭头函数的用法。传入createStore
构建store,此时因为无参数输入,enhancer为undefined。对所有middleware进行遍历,注入middlewareAPI,返回chain,即[f1(next), f2(next), f3(next), …],用compose
处理chain,主要目的是将middleware组合串联,f1(f2(f3(store.dispatch)))。
|
|
compose
的实现主要是这样的:
|
|
而对于thunkMiddleware
而言,传入参数{dispatch, getState}即为middlewareAPI,这里使用到了闭包,对于f1(f2(f3(store.dispatch)))而言,它的next为f2(f3(store.dispatch)),传入相应action后,会进行一个判断,若action为function则action(dispatch, getState),不然会利用next传给下一个middleware。
注意: 这里判断action是否为function的主要原因是部分action不需要到达store.dispatch,thunkMiddleware会对其进行拦截
|
|
让我们再回到示例的核心代码部分,这里尽量用少的代码来表达我的理解,具体的代码可自行研读。
(1) 当<select>
从reactjs切换到frontend时,触发onChange,dispatch(selectReddit(nextReddit))
,新的state形成,其中selectedReddit值变为frontend。
(2) 由于state的改变,触发componentWillReceiveProps(nextProps)
,发生在render前,这里会对nextProps与当前props中的selectedReddit进行比对,不同会触发dispatch(fetchPostsIfNeeded(selectedReddit))
,即向服务器请求相应的json。
(3) fetchPostsIfNeeded是一个作为action的function,dispatch(fetchPostsIfNeeded(selectedReddit))
中fetchPostsIfNeeded(selectedReddit)
会返回一个匿名函数,function(dispatch, getState)
即thunkMiddleware中的action,thunkMiddleware会向这个匿名function传入dispatch与getState。
|
|
(4)之后再执行相应的dispatch requestPosts与receivePosts操作。