redux-thunk
实现思路
redux-thunk相当于是基于store的升级,一般情况,我们传给store的action是一个对象,但是通过redux-thunk中间件,我们可以把部分的业务逻辑(异步请求)等放在action中进行处理。当store接收到函数类型的action,redux-thunk会执行该函数,并传入参数dispatch,当函数内部的逻辑执行完成后,会再次派发一个action继续向下执行。
// store中的index.js文件
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reduer from "./reduer";
// 使用react-devtools的配置
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk)
);
const store = createStore(reduer, enhancer);
export default store;
// store中的action文件
......
// 保存list数据的action
export const getListData = (data) => {
return {
type: GET_LIST_DATA,
data
}
}
// 异步通过接口获取list数据的action
export const getListDataAction = () => {
// 默认store只能识别对象的action,但是使用了thunk,可以通过传入一个函数,在thunk中间件中会执行
return (dispatch) => {
axios.get("api/todolist").then(res => {
const action = getListData(res.data);
dispatch(action);
}).catch((e) => {
console.log("获取数据失败了", e)
})
}
}
redux-saga
实现思路
在store的index文件中创建saga中间件连接到store,saga中间件可以监控派发的action,如果有action.type值与监控的变量一致,则执行该函数的内容,在这个函数中也可以再次派发一个新的action。
// store中的index.js文件
import { createStore, applyMiddleware, compose } from 'redux';
import createSagaMiddleware from 'redux-saga'
import reduer from "./reduer";
import mySaga from './sagas'
// 创建saga中间件
const sagaMiddleware = createSagaMiddleware();
// react-devtools的配置
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(sagaMiddleware)
);
const store = createStore(reduer, enhancer);
// 执行saga中间件
sagaMiddleware.run(mySaga)
export default store;
// sagas.js 文件
import { put, takeEvery } from "redux-saga/effects";
import { GET_LIST } from "./actiontypes";
import { getListDataAction } from "./renderStore"
import axios from "axios";
// 获取数据的函数
function* getListData() {
try {
// 使用异步的方式,拿到请求的结果
const res = yield axios.get("api/todolist");
// 获取到新的action
const action = getListDataAction(res.data);
// 派发新的action
yield put (action)
} catch (error) {
console.log("请求todolist数据失败了", error);
}
}
// 监控派发内容是 GET_LIST,都要执行一次 getListData函数
function* mySaga() {
yield takeEvery(GET_LIST, getListData);
}
export default mySaga;
react-redux
实现思路
在入口文件中,使用Provider包裹组件并注入store,在同一个的Provider标签中,store是可以共享的。在页面组件中,再使用connect将当前页面组件和派发的state和dispatch绑定,store中的state数据派发到props中,然后自定义的函数也同样派发到props上,这样就可以从props中获取到变量和方法了。
因为使用connect连接,当store发生变化的时候,对应的组件数据也会更新。
// 入口文件
import ReactDOM from 'react-dom';
import { Provider } from "react-redux";
import './index.css';
import TodoList from './todo.list';
import store from "./store";
ReactDOM.render(
<Provider store={store}>
<TodoList />
</Provider>,
document.getElementById('root')
);
// 页面组件
......
// 将store中的state派发到当前页面的props上
const mapStateToProps = (state) => ({
inputValue: state.inputValue,
list: state.list,
});
// 自定义函数,将其派发到当前页面组件的props上
const mapDispatchToProps = (dispatch) => ({
changeValue(e) {
const action = changeValueAction(e);
dispatch(action);
},
addItem() {
const action = addItemAction();
dispatch(action);
},
removeItem(index) {
const action = removeItemAction(index);
dispatch(action);
},
});
// connect 用于连接,将mapStateToProps和mapDispatchToProps两个方法,连接到TodoList上
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
对比
- redux-thunk和redux-saga中间件 相当于对store的升级,thunk通过执行action中的函数实现业务逻辑,没有拓展API;saga通过定义saga函数进行监控,同时提供一些常用的API;
- react-redux 不需要在construction中订阅store的变化,但是thunk和saga需要。
- react-redux将业务逻辑写在自定义的派发函数中,将函数派发到props中,从props中获取state中的值和自定义的函数。thunk将部分异步处理业务逻辑写在action中,saga则是放在监控的函数中。