React-Thunk在redux中获取异步数据
- 当前保存异步数据存在的问题
以前获取数据都是在组件的生命周期方法中进行获取并且在组件中存储,但是数据需要储存到redux中。异步数据既然要保存到Redux中, 所以获取异步数据也应该是Redux的一部分,所以获取异步数据的代码应该放到Redux中, 而不是放到组件生命周期方法中 - 如何在Redux中获取网络数据?
使用redux-thunk
中间件 - redux-thunk作用?
默认情况下dispatch
只能接收一个对象,
使用redux-thunk
可以让dispatch
除了可以接收一个对象以外, 还可以接收一个函数,是通过dispatch
派发一个函数的时候能够去执行这个函数, 而不是执行reducer
函数 - redux-thunk如何使用?
- 安装
redux-thunk
npm install redux-thunk
- 在创建
store
时应用redux-thunk
中间件
import { createStore, applyMiddleware } from 'redux' import thunkMiddleware from 'redux-thunk' //在创建redux之前告诉redux需要应用thunkMiddleware的中间件,其返回结果是一个对象 const storeEnhancer = applyMiddleware(thunkMiddleware); // 利用store来保存状态(state) const store = createStore(reducer, storeEnhancer);
- 在action中获取网络数据
export const getUserInfo = (dispatch, getState) =>{ fetch('http://127.0.0.1:7001/info') .then((response)=>{ return response.json(); }) .then((data)=>{ // console.log('在action中获取到的网络数据', data); dispatch(changeAction(data)); }) .catch((error)=>{ console.log(error); }) }
- 在组件中派发action
import React from 'react'; import { connect } from 'react-redux' import {addAction, subAction, getUserInfo} from '../store/action'; class About extends React.PureComponent{ componentDidMount() { this.props.changeInfo(); } render(){ return ( <div> <p>{this.props.count}</p> <button onClick={()=>{this.props.decrement()}}>递减</button> <p>{this.props.info.name}</p> <p>{this.props.info.age}</p> </div> ) } } // 在mapStateToProps方法中告诉React-Redux, 需要将store中保存的哪些数据映射到当前组件的props上 const mapStateToProps = (state)=>{ return { count: state.count, info: state.info } }; const mapDispatchToProps = (dispatch) =>{ return { decrement(){ dispatch(subAction(1)); }, changeInfo(info){ dispatch(getUserInfo); } } }; export default connect(mapStateToProps, mapDispatchToProps)(About);
官方文档地址: https://www.redux.org.cn/docs/advanced/AsyncActions.html
此时就实现了在redux里面获取数据和存储数据。
react-thunk执行流程
使用redux-thunk之前: -------------------- ------> | Component 异步请求 | ----- | -------------------- | | ↓ ------------- ------------- ------------- | Store | <---- | Reducer | <---- | Action | ------------- ------------- ------------- 使用redux-thunk之后: ------------- ---------> | Component | --------------------------------- | ------------- | | ↓ ------------- ------------- ------------- ------------- | Store | <---- | Reducer | <---- | 异步请求 | <---- | Action | ------------- ------------- ------------- -------------
React-thunk实现原理
在redux-thunk中:
- 如果通过dispatch派发的任务是一个对象, 那么就立即执行reducer
- 如果通过dispatch派发的任务是一个函数, 那么就执行这个函数
function thunkDispatch(action) { console.log('执行reducer之前做的事情'); if(typeof action === 'function'){ action(store.dispatch, store.getState); }else{ store.dispatch(action); } }
优化:将官方的dispatch改为我们自己的dispatch
function thunkDispatch(store) { const storeDispath = store.dispatch; const storeGetState = store.getState; function myDispatch(action) { if(typeof action === 'function'){ action(storeDispath, storeGetState); }else{ storeDispath(action); } } // 将官方的dispatch函数修改为我们自定义的dispatch函数 store.dispatch = myDispatch; } thunkDispatch(store); // 调用的实际是我们自定义的dispatch函数 store.dispatch(addAction); store.dispatch(getUserInfo);