Redux 和 Redux thunk 理解
1: state 就像 model
{
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
2: action, 普通的 javascript 对象, 用来描述发生了什么, 里面除了type 必须的, 还会其它属性值来改变 state。
{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
3. 为了把 action 和 state 串起来, 就是 reducer, 例如下面:
reducer 一定是对应于 action 里的 type 的值, 而做变化。
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([{ text: action.text, completed: false }]);
default:
return state;
}
}
Redux thunk 到底是怎么起作用的呢, 请看下面的代码:
const store = createStore(reducer, preloadedState, applyMiddleware(thunk));
当执行这个代码的时候, 实际执行了 applyMiddleware(thunk)(createStore)(reducer, preloadedState),
这个会返回一个新的 store对象, 这个 store对象的dispatch 发生了变化。
源码里首先定义原来的 store = createStore(reducer, preloadedState);
然后 thunk 里面传递下面的对象:
{ getState: store.getState, dispatch: (action) => dispatch(action) }
再传入原来的 store.dispatch(就是next),
返回的函数就是新的 dispatch方法:
action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }
所以当你执行, 下面的方法判断 action 是否是函数,
dispatch( incrementAsync() );
注意下面标红的 dispatch 跟 store.dispatch 一样,所以又重新执行了1遍 dispatch = compose(...chain)(store.dispatch);
但是这个时候的 action 已经是 increment(), 不是函数了, 所以直接走到 next(action) 里面了。
function incrementAsync(delay = 1000) { return dispatch => { setTimeout(() => { dispatch(increment()); }, delay); }; }
Redux thunk 官网源码
function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { //注意这里 dispatch 不用 next? return action(dispatch, getState, extraArgument); } // 注意这里 next 不用 dispatch return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
applyMiddleware 源码如下:
import compose from './compose' // 这货的作用其实就是 compose(f, g, h)(action) => f(g(h(action))) export default function applyMiddleware(...middlewares) { return function(createStore) { return function(reducer, preloadedState, enhancer) { // 用原 createStore 先生成一个 store,其包含 getState / dispatch / subscribe / replaceReducer 四个 API var store = createStore(reducer, preloadedState, enhancer) var dispatch = store.dispatch // 指向原 dispatch var chain = [] // 存储中间件的数组 // 提供给中间件的 API(其实都是 store 的 API) var middlewareAPI = { getState: store.getState, // 注意这里面的 dispatch 已经变成下面的 dispatch 了 dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) // 用原来的 store.dispatch 进行窜连 dispatch = compose(...chain)(store.dispatch) return { ...store, // store 的 API 中保留 getState / subsribe / replaceReducer dispatch // 新 dispatch 覆盖原 dispatch,往后调用 dispatch 就会触发 chain 内的中间件链式串联执行 } } } }