在实际项目的开发中,我们通常将我们异步请求的数据放在redux中进行存储,之前我们在组件中进行相应的异步请求,获取数据后通过dispath()将我们请求的数据保存到redux中,实际上这是有一定的违和感的,既然我们的数据就是保存在redux中,那么我们为什么不在redux中执行相应的异步操作呢,直接将数据保存在我们的redux中呢。实际上这就需要在我们的redux中进行相应的异步操作了。

1、组件中的异步操作

在之前简单的案例中,redux中保存的counter是一个本地定义的数据:

  • 我们可以直接通过同步的操作来dispatch action,state就会被立即更新。
  • 但是真实开发中,redux中保存的很多数据可能来自服务器,我们需要进行异步的请求,再将数据保存到redux中。

在之前学习网络请求的时候我们讲过,网络请求可以在class组件的componentDidMount中发送,所以我们可以有这样的结构:
image.png

1.1 在react组件中发送异步的网络请求

  1. import React, { PureComponent } from 'react'
  2. // 引入react-redux中的connect函数
  3. import { connect } from 'react-redux'
  4. import {incrementAction, addNumberAction,changeBannerAction, changeRecommendAction} from '../store/actionCreators'
  5. // 在react中发送响应的网络请求
  6. // 引入axios
  7. import axios from 'axios'
  8. class About extends PureComponent {
  9. componentDidMount() {
  10. axios({url: 'http://123.207.32.32:8000/home/multidata'}).then(res => {
  11. console.log(res.data);
  12. // 轮播图列表
  13. const banner = res.data.data.banner.list
  14. // 推荐列表
  15. const recommend = res.data.data.recommend.list
  16. // 可以通过action派发事件
  17. this.props.changeBanner(banner)
  18. this.props.changeRecommend(recommend)
  19. })
  20. }
  21. render() {
  22. return (
  23. <div>
  24. <h2>about组件</h2>
  25. <h2>当前技术:{this.props.counter}</h2>
  26. <button onClick={() => this.props.btn1Click() }>+1</button>
  27. <button onClick={() => this.props.btn2Click(5) }>+5</button>
  28. </div>
  29. )
  30. }
  31. }
  32. const mapStateToProps = state => {
  33. return {
  34. counter: state.counter
  35. }
  36. }
  37. const mapDispatchToProps = dispatch => {
  38. return {
  39. btn1Click() {
  40. dispatch(incrementAction())
  41. },
  42. btn2Click(num) {
  43. dispatch(addNumberAction(num))
  44. },
  45. changeBanner(banner) {
  46. dispatch(changeBannerAction(banner))
  47. },
  48. changeRecommend(recommend) {
  49. dispatch(changeRecommendAction(recommend))
  50. }
  51. }
  52. }
  53. export default connect(mapStateToProps, mapDispatchToProps)(About)

1.2 actionCreateor.js文件

  1. import { INCREMENT, ADD_NUMBER, DECREMENT, SUB_NUMBER, CHANGE_BANNER, CHANGE_RECOMMEND } from './constants'
  2. export const incrementAction = () => ({
  3. type: INCREMENT,
  4. })
  5. export const addNumberAction = num => ({
  6. type: ADD_NUMBER,
  7. num
  8. })
  9. export const decrementAction = () => ({
  10. type: DECREMENT
  11. })
  12. export const subNumberAction = num => ({
  13. type: SUB_NUMBER,
  14. num
  15. })
  16. // 修改banner的action
  17. export const changeBannerAction = banner => {
  18. return {
  19. type: CHANGE_BANNER,
  20. banner
  21. }
  22. }
  23. // 修改推荐数据的action
  24. export const changeRecommendAction = recommend => {
  25. return {
  26. type: CHANGE_RECOMMEND,
  27. recommend
  28. }
  29. }

1.3 constants.js常量文件

  1. const INCREMENT = 'INCREMENT';
  2. const ADD_NUMBER = 'ADD_NUMBER';
  3. const DECREMENT = 'DECREMENT';
  4. const SUB_NUMBER = 'SUB_NUMBER';
  5. // 修改banner和recommend
  6. const CHANGE_BANNER = 'CHANGE_BANNER';
  7. const CHANGE_RECOMMEND = 'CHANGE_RECOMMEND'
  8. export {
  9. INCREMENT,
  10. ADD_NUMBER,
  11. DECREMENT,
  12. SUB_NUMBER,
  13. CHANGE_BANNER,
  14. CHANGE_RECOMMEND
  15. }

1.4 reducer.js处理函数文件

  1. import { INCREMENT, ADD_NUMBER, DECREMENT, SUB_NUMBER, CHANGE_BANNER, CHANGE_RECOMMEND } from './constants'
  2. const defaultState = {
  3. counter: 100,
  4. banner: [],
  5. recommend: []
  6. }
  7. function reducer(state = defaultState, action) {
  8. switch(action.type) {
  9. case INCREMENT:
  10. return {...state, counter: state.counter + 1 }
  11. case ADD_NUMBER:
  12. return {...state, counter: state.counter + action.num }
  13. case DECREMENT:
  14. return {...state, counter: state.counter - 1 }
  15. case SUB_NUMBER:
  16. return {...state, counter: state.counter - action.num }
  17. // 处理banner和recommend
  18. case CHANGE_BANNER:
  19. return {...state, banner: action.banner }
  20. case CHANGE_RECOMMEND:
  21. return {...state, recommend: action.recommend }
  22. default:
  23. return state
  24. }
  25. }
  26. export default reducer;

1.5 在实际业务组件中使用react-redux中的数据

  1. import React, { PureComponent } from 'react'
  2. // 引入connect函数
  3. // import connect from '../utils/connect'
  4. import { connect } from 'react-redux'
  5. import {decrementAction, subNumberAction} from '../store/actionCreators'
  6. class About extends PureComponent {
  7. render() {
  8. return (
  9. <div>
  10. <h2>Home组件</h2>
  11. <h2>当前技术:{this.props.counter}</h2>
  12. <button onClick={() => this.props.increment() }>-1</button>
  13. <button onClick={() => this.props.addNumber(5) }>-5</button>
  14. <hr/>
  15. <h2>轮播图</h2>
  16. <ul>
  17. {
  18. this.props.banner.map(item => {
  19. return (
  20. <li key={item.acm}>
  21. <span>{ item.title }</span>
  22. <a href={item.image} style={{ marginLeft: '10px'}}>点击查看图片</a>
  23. </li>
  24. )
  25. })
  26. }
  27. </ul>
  28. <h2>推荐列表</h2>
  29. <ul>
  30. {
  31. this.props.recommend.map(item => <li key={item.acm}>{item.title}</li>)
  32. }
  33. </ul>
  34. </div>
  35. )
  36. }
  37. }
  38. const mapStateToProps = state => {
  39. return {
  40. counter: state.counter,
  41. # 非常重要
  42. banner: state.banner,
  43. recommend: state.recommend
  44. }
  45. }
  46. const mapDispatchToProps = dispatch => {
  47. return {
  48. increment() {
  49. dispatch(decrementAction())
  50. },
  51. addNumber(num) {
  52. dispatch(subNumberAction(num))
  53. }
  54. }
  55. }
  56. // 函数柯里化
  57. 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即可。