最近在初學(xué)redux,也接著學(xué)了redux里的中間件。
對于redux,本來 store.dispatch 只能派發(fā)的是一個對象給store。
加了 redux 中間件后:其實是對 store.dispatch 方法做了升級;升級后可接收對象,也可接收函數(shù),使得可處理異步代碼了
如果派發(fā)的的是對象,則中間件會直接傳給store;如果派發(fā)的是函數(shù)的話,則會先執(zhí)行這個函數(shù)
注意:這里的中間件指的是 store 和 action 的中間
常見的 redux 中間件 :redux-thunk 和 redux-saga 都是處理異步的
前者是通過把異步代碼放在action里,后者是把異步代碼單獨放在一個文件里
先將 redux-thunk 中間件
Redux-thunk
Redux-thunk思想: 異步請求放到action里
安裝:
npm install redux-thunk
引入:
在創(chuàng)建store的地方引入這個中間件
即在store目錄下的 index.js 引入react 的 applyMiddleware 和 redux-thunk,
然后在用 createStore () 方法中,設(shè)第二個參數(shù):通過 applyMiddleware ()方法使用 redux-thunk 這個中間件
//栗子
import {createStore, applyMiddleware} from 'redux'
import reducer from './reducer.js'
import thunk from 'redux-thunk'
export default createStore(
reducer,
applyMiddleware(thunk)
);
注:Chrome插件也是屬于中間件, 如果也想擴展 redux-devtools (也原本是放createStore第二個參數(shù)) 因為多使用了一些中間件,比如 redux-thunk 后,則createStore()的第二個參數(shù)的 applyMiddleware() 不能是redux-devtools 擴展Chrome插件的那些代碼了
若既想要使用 redux-devtools 這個 Chrome 擴展插件,又想使用中間件的話
怎么辦:GitHub 的 redux-devtools-extension 提供了解決方法
https://github.com/zalmoxisus/redux-devtools-extension
import {createStore, applyMiddleware, compose} from 'redux'
import reducer from './reducer.js'
import thunk from 'redux-thunk'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk)
);
const store = createStore(reducer, enhancer);
export default store
使用: 在action中使用redux-thunk
本來 action/ actionCreateor.js 應(yīng)該返回的是對象,使用了redux-thunk 后則也可return 返回一個函數(shù)了,在這個函數(shù)里去寫異步代碼(如ajax請求)
由于 action 此時是函數(shù)了,所以 react 會去執(zhí)行這個函數(shù);
在這個函數(shù)里如果想把數(shù)據(jù)更新到 store 上的話,又是同樣的 store.dispatch (一個action),不過由于此時這個return 返回的函數(shù)接收到的參數(shù)就是store.dispatch方法,則可直接dispatch(action對象)
// 栗子
// 組件里
componentDidMount(){
const action = getTodolist();
store.dispatch(action)
}
// actionCreateor.js文件
export const initListAction =(data)=>({
type: INIE_TODOLIST,
value: data
})
export const getTodolist =()=>{
return (dispatch)=>{
axios.get('./list.json').then((res)=> {
const data = res.data;
const action = initListAction(data);
dispatch(action)
})
}
}
// reducer.js 文件里
export const initListAction =(data)=>({
type: INIE_TODOLIST,
value: data
})
我的總結(jié)思路:
先 store.dispatch 一個函數(shù),這個函數(shù)返回的也是函數(shù)A,
在這個返回的函數(shù)A里寫的是異步的代碼,和進一步的真正的action事件的派發(fā)(第二次store.dispatch(),且派發(fā)的這個對象的數(shù)據(jù)就是來自異步后的數(shù)據(jù))