在实际项目的开发中,我们通常将我们异步请求的数据放在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中发送响应的网络请求
// 引入axios
import 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的action
export const changeBannerAction = banner => {
return {
type: CHANGE_BANNER,
banner
}
}
// 修改推荐数据的action
export 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和recommend
const 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和recommend
case 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即可。