什么是中间件
Redux标准流程:View(React视图层)会派发一个Action对象,Action通过dispatch方法会派发给Store,Store接收到Action连同之前的State一起交给Reducer处理,Reducer返回一个新的数据State,Store用新的State来替换旧的State。
中间件指的是Action和Store中间对dispatch方法的封装或升级,使得dispatch方法根据参数的不同执行不同的动作:参数是Action对象,按照标准流程执行;参数是Action函数,就先执行该函数,在该函数中合适的地方继续进行数据的传递。
Redux的中间件有很多种,本文使用Redux-thunk和Redux-saga。
一、Redux不使用中间件发送Ajax
整体流程:
- 发送ajax请求放在
componentDidMount
生命周期函数中 - 得到响应后创建action,即定义
initListAction(data)
- 把action传递给store
- Reducer处理响应数据并返回
TodoList组件:
componentDidMount() {
axios.get('/api/todolist').then((res)=>{
const data=res.data;
const action =initListAction(data);
store.dispatch(action);
console.log(res);
}).catch((err)=>{
console.log(err);
})
}
actionCreator.js:
export const initListAction = (data) => ({
type:INIT_LIST_ITEM,
data
});
actionTypes.js:
export const INIT_LIST_ITEM='init_list_item';
Reducer处理逻辑:
if(action.type===INIT_LIST_ITEM){
const newState=JSON.parse(JSON.stringify(state));
newState.list=action.data;
return newState;
}
二、使用Redux-thunk中间件发送Ajax
我的项目地址:https://gitee.com/XiaoYuZhou233/React-TodoList/tree/Redux5
1. 安装
详见官网:https://github.com/reduxjs/redux-thunk
用npm
命令安装Redux-thunk
npm install --save redux-thunk
2. 在store中使用该中间件:
//Store 的创建
import reducer from './reducer'
import { createStore, applyMiddleware,compose } from 'redux';
import thunk from 'redux-thunk';
//applyMiddleware函数:用于Redux中间件的使用,参数是中间件名,也可以用数组形式使用多个中间件
const store = createStore(
reducer,
applyMiddleware(thunk)
);
export default store;
3.异步处理
该中间件可以让我们在action中写异步代码,在actionCreator中:
=>>>使用Redux-thunk之后,可以返回一个函数
export const getTodoList = ()=>{
return (dispatch)=>{
axios.get('/api/todolist').then((res)=>{
const data=res.data;
//调用之前的initListAction方法来初始化state
const action =initListAction(data);
//在这一步才真正将数据传到了store并用Reducer进行处理
dispatch(action);
}).catch((err)=>{
console.log(err);
})
}
};
4.在生命周期函数中使用
在父组件中,使用:
componentDidMount() {
//使用了Redux-thunk中间件,可以将异步(即发送请求)操作移除,到actionCreator中
//这个action不再是一个对象,而是一个函数
const action=getTodoList();
// 该函数自动执行,该函数自动执行,代码转到该函数
store.dispatch(action);
}
三、使用Redux-saga中间件发送Ajax
我的项目地址:https://gitee.com/XiaoYuZhou233/React-TodoList/tree/Redux6
1. 安装
详见官网:https://github.com/redux-saga/redux-saga
用npm
命令安装Redux-saga
npm install --save redux-saga
2. 在store中使用该中间件:
//Store 的创建
import reducer from './reducer'
import { createStore, applyMiddleware,compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import todoSagas from './sagas'
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
);
// then run the saga
sagaMiddleware.run(todoSagas);
export default store;
3.异步处理
创建sagas.js文件
=>该文件跟Reducer有着相同的功能,会接收到TodoList派发的action,
=>即可将异步逻辑写在此文件
import { call, put, takeEvery} from 'redux-saga/effects'
import {GET_INIT_LIST} from './actionTypes'
import {initListAction} from "./actionCreators";
import axios from 'axios';
/*
generator函数
*/
function* fetchUser() {
//请求的返回结果直接保存在了res中,yield含义是等待请求处理完成之后再执行代码
const res = yield axios.get('/api/todolist');
// 创建action
const action = initListAction(res.data);
//用下面的代码代替store.dispatch(action);
yield put(action);
}
/*
generator函数
*/
function* mySaga() {
//捕捉每一个这样type的action,每次捕捉到就会执行fetchUser这个方法
yield takeEvery(GET_INIT_LIST, fetchUser);
}
export default mySaga;
4.修改actionCreator
//发送请求,根据返回数据得到列表项
export const initListAction = (data) => ({
type:INIT_LIST_ITEM,
data
});
//获取初始列表的action
export const getInitList = () => ({
type:GET_INIT_LIST
});
5.在生命周期函数中使用
在父组件中,使用:
componentDidMount() {
const action=getInitList(); // 从actionCreator中引入
store.dispatch(action);
}
使用中间件的好处是什么?可以参考阮一峰博客Redux 入门教程(二):中间件与异步操作