咱們知道,redux提供了一套很好的狀態管理機制,經過在createStore方法建立出store對象,經過store.getState獲取狀態對象,經過reducer定義出action改變對應的state變化的規則,經過replaceReducer動態改變reducer規則,結合dispatch一個action來修改狀態對象state,甚至,redux還提供了applyMiddleware來給redux增長中間件,提供dispatch和getState2個方法給中間件使用;react
不過,redux只是一個和其餘庫無關的狀態管理庫,爲了可以方便的在react中使用,咱們必須結合react-redux來使用。react-redux經過Provider使用給react項目的全部子組件注入store,經過connect給組件注入state和dispatch。ajax
可是,有了react-redux還不夠!咱們還須要react-thunk!redux
ajax請求發出去的時候,常常涉及到這3個狀態:loading,success,error3個狀態,並且這3個狀態是在同一個地方產生的,那麼,若是僅有react-thunk,那麼,咱們須要在組件內部這樣寫代碼:api
this.props.dispatch(loadingAction); ajax('/getData').then(res => { this.props.dispatch(successAction); }).catch(err => { this.props.dispatch(errorAction); })
若是上述代碼在組件內屢次被調用,就須要封裝成函數,getData,若是要誇頁面調,那就須要封裝到專門的api請求裏面去,代碼以下:app
//api.js export function getData(dispatch) { this.props.dispatch(loadingAction); ajax('/getData').then(res => { this.props.dispatch(successAction); }).catch(err => { this.props.dispatch(errorAction); }); } //index.js業務組件代碼 import {getData} from './api.js'; class MyComponent extends Component { handleClick() { getData(this.props.dispatch); } }
而且,若是getData內部須要用到全局的state,那麼,咱們必需要從業務代碼裏面傳入getState函數,那麼代碼就會變成下面這樣:ide
//api.js export function getData(dispatch, getState) { const state = getState(); dispatch(loadingAction); ajax('/getData').then(res => { dispatch(successAction); }).catch(err => { dispatch(errorAction); }); } //index.js業務組件代碼 import {getData} from './api.js'; class MyComponent extends Component { handleClick() { getData(this.props.dispatch, this.props.store.getState); } }
彷佛這樣也行,可是,總感受不對,每次都要從業務組件裏面顯式的傳入2個參數dispatch和getState,這樣感受很煩。
因此呢,經過以上分析,咱們react-thunk就閃亮登場了!函數
//store.js import thunk from 'redux-thunk'; const initialState = {}; const reducer = function(state={}, action){ return state }; const store = createStore(reducer, initialState, applyMiddleware(thunk)); //action.js export function getData(dispatch, getState) { const state = getState(); dispatch(loadingAction); ajax('/getData').then(res => { dispatch(successAction); }).catch(err => { dispatch(errorAction); }); } //index.js業務組件代碼 import { getData } from './actions.js'; class MyComponent extends Component { handleClick() { getData(); } }
這樣,使用了react-thunk以後,咱們無需從getData中傳入dispatch和getState,而是中間件會默認幫咱們作這個事情,這樣,咱們就能夠在一個函數內部dispatch多個action,以及隨意的拿到全局的statethis
看源碼:spa
//一個建立thunk的中間件工廠函數 function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } //建立出thunk中間件 const thunk = createThunkMiddleware(); //把工廠函數附屬到thunk對象上,方便高級用戶自定義傳入更多的參數到action中去 thunk.withExtraArgument = createThunkMiddleware; export default thunk;
其實,就是一箇中間件的寫法,當發現action是一個函數的時候,就會傳入dispatch和getState這2個參數,而這2個參數是從中間件那裏傳過來的。code
全文完