一年前看过一遍,看完后感觉良好,但是过了一段时间一些细节记不清了,Orz。今年再看一遍,顺便记录下来。
Redux 这方面必须整得明明白白
https://www.lingchenxuan.com/2017/07/04/Redux,-Redux-thunk-%E5%92%8C-React-Redux-%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/
Redux
目录结构
|
|
compose(…funcs)
工具方法,在applyMiddleware中使用。
|
|
bindActionCreators(actionCreators, dispatch)
用 dispatch 封装 actionCreator,可以让
Redux 相对组件透明,降低耦合度。
|
|
combineReducers(reducers)
合并 reducers,大项目一定会用到的 api,拆分逻辑,模块化 reducer。
|
|
createStore(reducer, preloadedState, enhancer)
终极核心 api,Redux 中的一切都是围绕着 store(state) 来运转的。
createStore() 可以算 store 的构造函数了,store的所有方法都是在这里定义的。
state 存放在 createStore() 这个闭包里,所以只能用 getState 来获取。
dispatch, subscribe, getState, replaceReducer,
四个核心 api,代码都相当简单。
以下代码删去了一些校验代码,只保留核心代码。
|
|
applyMiddleware(…middlewares)
终于到最后一个api了,嘎嘎。
同样是非常简短的源码,但是却最值得细读回味。
|
|
一个中间件一般是长这样的
|
|
然后经过
|
|
chain 里每个元素就变成了这个样子:
|
|
那么现在有三个中间件:
|
|
类似的 chain 里面也有三个被扔进了 store 的函数。
每个函数里的 next 都是之后中间件逻辑的组合。
这里有个点:M1(M2(M3(dispatch)))
粗粗一看,一定是以为M3会先执行。
这样顺序不就不对了吗?其实,确实是 M3 先执行,但是 M3 只是 return 了一个 function ,并没有执行里面的逻辑。
所以最终是 M1 得到了 M2 , M3 和 dispatch 的逻辑封装,先执行 M1 的逻辑,打印。
执行到中间,碰到了 next,这个 next 就是我上面说的那一大串逻辑封装函数。
以此类推,M2 和 M3 在 next 之前的代码都会依次执行。
M3 的 next 是真正的 dispatch 了,没有其它中间件。
于是,接着会依次执行 M3 余下的逻辑, M2 余下的逻辑, M1余下的逻辑,直至跳出整个函数。
这就是洋葱模型,几个同心圆代表各个中间件,一条直线从圆心穿过,有始有终,放得初心。
一个简化的洋葱模型,只要搞懂了这个,Redux 的中间件的基本原理就算整明白了,嘿嘿。
|
|
Redux Thunk
简介
首先港一下,Redux 里面是可以异步调用 dispatch() 的,比如:
|
|
恩,没毛病。但是这样有许多不便之处,可以看看这个回答,了解有什么不便之处,主要是手动传递 dispatch 和难以分辨普通的 actionCreator。
This was the motivation for finding a way to “legitimize” this pattern of providing dispatch to a helper function, and help Redux “see” such asynchronous action creators as a special case of normal action creators rather than totally different functions.
所以就诞生了 Redux Thunk。
Redux Thunk 可以让 action 作为一个函数,并传递dispatch和getState作为参数。
源码
|
|
啥是 thunk
作者是这样描述的:
A thunk is a function that wraps an expression to delay its evaluation.
thunk 首先它是一个函数,然后这个函数里面封装了一个要延迟执行的表达式。
React Redux
看的我头好晕啊。+_+ 没想到小小的 React Redux 里面这么绕。
简单的港港吧,具体细节以后再补齐。
Provider
|
|
Provider 这个组件的功能比较简单,将 store 挂在 context 上。
利用 React context 的特性,使所有
Provider 的子组件都可以访问到 store。
因此,connect 高阶组件可以轻松地获取 store。
Connect
|
|
在构造函数中,从 context 中获得 store,并初始化 selector (一个对象,作用是在初始化和 update 的时候 mapStateToProps)。
在 componentDidMount() 中,调用
store 的 subscribe(),将onStateChange()作为回调传入。
在 state 更新时,触发onStateChange(),组件 setState(dummyState)。(dummyState是一个空对象,但以前的版本当中,是整个
store 的 state)
组件更新,selector getState() 并重新map数据,更新props,子组件因此更新。