在实际项目的开发中,我们通常将我们异步请求的数据放在redux中进行存储,之前我们在组件中进行相应的异步请求,获取数据后通过dispath()将我们请求的数据保存到redux中,实际上这是有一定的违和感的,既然我们的数据就是保存在redux中,那么我们为什么不在redux中执行相应的异步操作呢,直接将数据保存在我们的redux中呢。实际上这就需要在我们的redux中进行相应的异步操作了。
1、组件中的异步操作
在之前简单的案例中,redux中保存的counter是一个本地定义的数据:
- 我们可以直接通过同步的操作来dispatch action,state就会被立即更新。
- 但是真实开发中,redux中保存的很多数据可能来自服务器,我们需要进行异步的请求,再将数据保存到redux中。
在之前学习网络请求的时候我们讲过,网络请求可以在class组件的componentDidMount中发送,所以我们可以有这样的结构:
1.1 在react组件中发送异步的网络请求
import React, { PureComponent } from 'react'// 引入react-redux中的connect函数import { connect } from 'react-redux'import {incrementAction, addNumberAction,changeBannerAction, changeRecommendAction} from '../store/actionCreators'// 在react中发送响应的网络请求// 引入axiosimport axios from 'axios'class About extends PureComponent {componentDidMount() {axios({url: 'http://123.207.32.32:8000/home/multidata'}).then(res => {console.log(res.data);// 轮播图列表const banner = res.data.data.banner.list// 推荐列表const recommend = res.data.data.recommend.list// 可以通过action派发事件this.props.changeBanner(banner)this.props.changeRecommend(recommend)})}render() {return (<div><h2>about组件</h2><h2>当前技术:{this.props.counter}</h2><button onClick={() => this.props.btn1Click() }>+1</button><button onClick={() => this.props.btn2Click(5) }>+5</button></div>)}}const mapStateToProps = state => {return {counter: state.counter}}const mapDispatchToProps = dispatch => {return {btn1Click() {dispatch(incrementAction())},btn2Click(num) {dispatch(addNumberAction(num))},changeBanner(banner) {dispatch(changeBannerAction(banner))},changeRecommend(recommend) {dispatch(changeRecommendAction(recommend))}}}export default connect(mapStateToProps, mapDispatchToProps)(About)
1.2 actionCreateor.js文件
import { INCREMENT, ADD_NUMBER, DECREMENT, SUB_NUMBER, CHANGE_BANNER, CHANGE_RECOMMEND } from './constants'export const incrementAction = () => ({type: INCREMENT,})export const addNumberAction = num => ({type: ADD_NUMBER,num})export const decrementAction = () => ({type: DECREMENT})export const subNumberAction = num => ({type: SUB_NUMBER,num})// 修改banner的actionexport const changeBannerAction = banner => {return {type: CHANGE_BANNER,banner}}// 修改推荐数据的actionexport const changeRecommendAction = recommend => {return {type: CHANGE_RECOMMEND,recommend}}
1.3 constants.js常量文件
const INCREMENT = 'INCREMENT';const ADD_NUMBER = 'ADD_NUMBER';const DECREMENT = 'DECREMENT';const SUB_NUMBER = 'SUB_NUMBER';// 修改banner和recommendconst CHANGE_BANNER = 'CHANGE_BANNER';const CHANGE_RECOMMEND = 'CHANGE_RECOMMEND'export {INCREMENT,ADD_NUMBER,DECREMENT,SUB_NUMBER,CHANGE_BANNER,CHANGE_RECOMMEND}
1.4 reducer.js处理函数文件
import { INCREMENT, ADD_NUMBER, DECREMENT, SUB_NUMBER, CHANGE_BANNER, CHANGE_RECOMMEND } from './constants'const defaultState = {counter: 100,banner: [],recommend: []}function reducer(state = defaultState, action) {switch(action.type) {case INCREMENT:return {...state, counter: state.counter + 1 }case ADD_NUMBER:return {...state, counter: state.counter + action.num }case DECREMENT:return {...state, counter: state.counter - 1 }case SUB_NUMBER:return {...state, counter: state.counter - action.num }// 处理banner和recommendcase CHANGE_BANNER:return {...state, banner: action.banner }case CHANGE_RECOMMEND:return {...state, recommend: action.recommend }default:return state}}export default reducer;
1.5 在实际业务组件中使用react-redux中的数据
import React, { PureComponent } from 'react'// 引入connect函数// import connect from '../utils/connect'import { connect } from 'react-redux'import {decrementAction, subNumberAction} from '../store/actionCreators'class About extends PureComponent {render() {return (<div><h2>Home组件</h2><h2>当前技术:{this.props.counter}</h2><button onClick={() => this.props.increment() }>-1</button><button onClick={() => this.props.addNumber(5) }>-5</button><hr/><h2>轮播图</h2><ul>{this.props.banner.map(item => {return (<li key={item.acm}><span>{ item.title }</span><a href={item.image} style={{ marginLeft: '10px'}}>点击查看图片</a></li>)})}</ul><h2>推荐列表</h2><ul>{this.props.recommend.map(item => <li key={item.acm}>{item.title}</li>)}</ul></div>)}}const mapStateToProps = state => {return {counter: state.counter,# 非常重要banner: state.banner,recommend: state.recommend}}const mapDispatchToProps = dispatch => {return {increment() {dispatch(decrementAction())},addNumber(num) {dispatch(subNumberAction(num))}}}// 函数柯里化export default connect(mapStateToProps, mapDispatchToProps)(About)
1.6 在组件中使用react-redux的步骤总结
在组件中异步请求的数据如何交给我们的redux进行管理: 1、在类组件的生命周期函数componentDidMount() 中发送异步请求,并获取相应的异步数据。
2、将我们需要dispatch派发action的地方定义一个方法,这个方法将在组件中映射为mapStateToDispatch(),我们的组件获取了异步数据后,调用这个方法、派发相应的action。
3、当派发了相应的action后,就会自动调用我们的reducer方法,reducer函数集那个会根据我们action.type的类型对数据进行保存和相应的处理。此时我们的数据就实时的保存进了redux的store中了。
4、在其它的业务组件中如何使用store中的state,我们需要的数据在在mapStateToProps()中声明即可。那么此时我们的store中的状态就会映射为相应状态,只需要在组件中使用我们的props即可。
