最近在初学redux,也接着学了redux里的中间件。
对于redux,本来 store.dispatch 只能派发的是一个对象给store。
加了 redux 中间件后:其实是对 store.dispatch 方法做了升级;升级后可接收对象,也可接收函数,使得可处理异步代码了
如果派发的的是对象,则中间件会直接传给store;如果派发的是函数的话,则会先执行这个函数
注意:这里的中间件指的是 store 和 action 的中间
常见的 redux 中间件 :redux-thunk 和 redux-saga 都是处理异步的
前者是通过把异步代码放在action里,后者是把异步代码单独放在一个文件里
先将 redux-thunk 中间件
Redux-thunk
Redux-thunk思想: 异步请求放到action里
安装:
npm install redux-thunk
引入:
在创建store的地方引入这个中间件
即在store目录下的 index.js 引入react 的 applyMiddleware 和 redux-thunk,
然后在用 createStore ()
方法中,设第二个参数:通过 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第二个参数) 因为多使用了一些中间件,比如 redux-thunk 后,则createStore()的第二个参数的 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 应该返回的是对象,使用了redux-thunk 后则也可return 返回一个函数了,在这个函数里去写异步代码(如ajax请求)
由于 action 此时是函数了,所以 react 会去执行这个函数;
在这个函数里如果想把数据更新到 store 上的话,又是同样的 store.dispatch (一个action),不过由于此时这个return 返回的函数接收到的参数就是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
})
我的总结思路:
先 store.dispatch
一个函数,这个函数返回的也是函数A,
在这个返回的函数A里写的是异步的代码,和进一步的真正的action事件的派发(第二次store.dispatch(),且派发的这个对象的数据就是来自异步后的数据)