网络知识 娱乐 <react求和案例>react-redux基本使用与优化——Provider/mapDispatch

<react求和案例>react-redux基本使用与优化——Provider/mapDispatch

文章目录

  • ⭐react-redux基本使用
    • ⛳求和案例_react-redux基本使用总结
  • ⭐优化1:简写mapDispatch
  • ⭐优化2:Provider组件的使用
  • ⭐优化3:整合UI组件与容器组件
    • ⛳求和案例_react-redux优化总结

上篇文章初步了解和学习了react-redux的原理和组件拆分
今天探索一下react-redux基本使用以及对求和案例的代码优化
感兴趣的小伙伴一起来看看吧!🤞

在这里插入图片描述

⭐react-redux基本使用

依旧对求和案例进行分析:
在这里插入图片描述

根据react-redux模型图,实现了Count的容器组件与Count的UI组件的联系,接下来要实现容器组件给UI组件传递 redux中所保存的状态以及操作状态的方法,要借助props

但是不能像原先父子组件传参利用标签的方式传递,比如:

<A>
  <B a='1' b='2'/>
<A/>

那么如何在容器组件(父组件)向UI组件传递参数呢?

由于父子组件关系是靠connect形成的,所以connect函数在第一次调用的时候要传入两个参数,参数必须是函数类型的,这样react-redux库就帮你调用这两个函数,一个函数返回值作为状态,另一个函数返回值作为操作状态的方法。

// react-redux API默认要给connect两个函数作为参数,两个函数会收到来至redux传来的值和方法。
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

mapStateToProps()函数的返回值作为 状态 传递给了UI组件,函数返回的是一个对象,mapStateToProps函数返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value。

由于要获取redux里的状态,就要store.getState(),就要在容器组件里引入store,但是之前已经在上层App.jsx里向容器组件传了store,就不需要自己引入了,这里也不需要我们自己去获取状态,react-redux帮我们调mapStateToProps()函数时,已经帮我们把状态传过去了,只需要mapStateToProps(state)接收一下即可。

function mapStateToProps(state) {
  return { count: state }
}

这样UI组件就可以通过 this.props 接收到 状态

<h1>当前求和为:{this.props.count}</h1>

mapDispatchToProps()函数的返回值作为 操作状态的方法 传递给了UI组件,函数返回的是一个对象,mapDispatchToProps函数返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value。

由于要实现加这个运算,就要在jia这个回调函数里通知redux执行加法,就要调用store.dispatch(action)这个方法,这里又要引入store操作状态,但是这里也不需要store调用dispatch方法,react-redux帮我们把dispatch()方法传过去了,直接用即可。

// 引入action
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/count_action'
function mapDispatchToProps(dispatch) {
  return {
    jia: (number) => {
      // 通知redux执行加法
      dispatch(createIncrementAction(number))
    },
    jian: (number) => {
      // 通知redux执行减法
      dispatch(createDecrementAction(number))
    },
    jiaAsync: (number, time) => {
      // 通知redux执行异步加法
      dispatch(createIncrementAsyncAction(number, time))
    }
  }
}

这样UI组件就可以通过 this.props 接收到 操作状态的方法

// 加法
increment = () => {
  // 获取用户输入
  const { value } = this.selectNumber
  this.props.jia(value * 1)
}

// 减法
decrement = () => {
  // 获取用户输入
  const { value } = this.selectNumber
  this.props.jian(value * 1)
}

// 奇数再加
incrementIfOdd = () => {
  // 获取用户输入
  const { value } = this.selectNumber
  if (this.props.count % 2 !== 0) {
    this.props.jia(value * 1)
  }
}

// 异步加
incrementAsync = () => {
  // 获取用户输入
  const { value } = this.selectNumber
  this.props.jiaAsync(value * 1, 500)
}

src=> components=> Count => index.jsx:

import React, { Component } from 'react'

export default class Count extends Component {

  // 加法
  increment = () => {
    // 获取用户输入
    const { value } = this.selectNumber
    this.props.jia(value * 1)
  }

  // 减法
  decrement = () => {
    // 获取用户输入
    const { value } = this.selectNumber
    this.props.jian(value * 1)
  }

  // 奇数再加
  incrementIfOdd = () => {
    // 获取用户输入
    const { value } = this.selectNumber
    if (this.props.count % 2 !== 0) {
      this.props.jia(value * 1)
    }
  }

  // 异步加
  incrementAsync = () => {
    // 获取用户输入
    const { value } = this.selectNumber
    this.props.jiaAsync(value * 1, 500)
  }

  render() {
    // console.log('UI组件接收到的props是:', this.props)
    return (
      <div>
        <h1>当前求和为:{this.props.count}</h1>
        <select ref={c => this.selectNumber = c}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;
        <button onClick={this.increment}>+</button>&nbsp;
        <button onClick={this.decrement}>-</button>&nbsp;
        <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
        <button onClick={this.incrementAsync}>异步加</button>
      </div>
    )
  }
}

src=> containers=> Count => index.jsx:

// 引入Count的UI组件
import CountUI from '../../components/Count'
// 引入action
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/count_action'

// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'

function mapStateToProps(state) {
  return { count: state }
}

function mapDispatchToProps(dispatch) {
  return {
    jia: (number) => {
      // 通知redux执行加法
      dispatch(createIncrementAction(number))
    },
    jian: (number) => {
      dispatch(createDecrementAction(number))
    },
    jiaAsync: (number, time) => {
      dispatch(createIncrementAsyncAction(number, time))
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

⛳求和案例_react-redux基本使用总结

1️⃣明确两个概念:

  • UI组件:不能使用任何redux的api,只负责页面的呈现、交互等。
  • 容器组件:负责和redux通信,将结果交给UI组件

2️⃣如何创建一个容器组件———依靠react-redux的connect函数

connect(mapStateToProps,mapDispatchToProps)(UI组件)

  • mapStateToProps:映射状态,返回值是一个对象
  • mapDispatchToProps:映射操作状态的方法,返回值是一个对象

3️⃣ 备注:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入

⭐优化1:简写mapDispatch

优化前:

// 映射状态
function mapStateToProps(state) {
  return { count: state }
}

优化后:

// 映射状态
const mapStateToProps = state => ({ count: state })

优化前:

// 映射操作状态的方法
function mapDispatchToProps(dispatch) {
  return {
    jia: (number) => {
      // 通知redux执行加法
      dispatch(createIncrementAction(number))
    },
    jian: (number) => {
      dispatch(createDecrementAction(number))
    },
    jiaAsync: (number, time) => {
      dispatch(createIncrementAsyncAction(number, time))
    }
  }
}

优化后:

// 映射操作状态的方法
const mapDispatchToProps = dispatch => (
  {
    jia: number => dispatch(createIncrementAction(number)),
    jian: number => dispatch(createDecrementAction(number)),
    jiaAsync: (number, time) => 
    dispatch(createIncrementAsyncAction(number, time))
  }
)

再优化后:

// 引入Count的UI组件
import CountUI from '../../components/Count'
// 引入action
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/count_action'

// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'

//使用connect()()创建并暴露一个Count的容器组件
// react-redux API默认要给connect两个函数作为参数,两个函数会收到来至redux传来的值和方法。
export default connect(
  state => ({ count: state }),
  dispatch => (
    {
      jia: number => dispatch(createIncrementAction(number)),
    	jian: number => dispatch(createDecrementAction(number)),
    	jiaAsync: (number, time) => 
    	dispatch(createIncrementAsyncAction(number, time))
    }
  )
)(CountUI)

mapDispatchToProps的简写:

export default connect(
  state => ({ count: state }),

  // mapDispatchToProps的一般写法
  // dispatch => (
  //   {
  //     jia: number => dispatch(createIncrementAction(number)),
  //     jian: number => dispatch(createDecrementAction(number)),
  //     jiaAsync: (number, time) =>
  //       dispatch(createIncrementAsyncAction(number, time))
  //   }
  // )

  // mapDispatchToProps的简写
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }
)(CountUI)

分析mapDispatchToProps的简写

{
  jia: createIncrementAction,
  jian: createDecrementAction,
  jiaAsync: createIncrementAsyncAction
}

Count的UI组件里调用了jia函数,传递了用户选择的参数,然后在容器组件里调用了createIncrementAction方法,返回值是一个action对象,react-redux帮我们自动dispatch了。

mapDispatchToProps可以写成一个普通的函数,也可以是一个对象

react-redux还有一个优势:不用自己监测redux的状态是否发生了变化,内部的所有逻辑全部交给容器组件来完成,避免污染整个app组件。

⭐优化2:Provider组件的使用

App.jsx:

import React, { Component } from 'react'
import Count from './containers/Count'
import store from './redux/store'

export default class App extends Component {
  render() {
    return (
      <div>
        {/* 渲染容器组件,给容器组件传递store */}
        <Count store={store} />
      </div>
    )
  }
}

当项目中有多个容器组件时,每次都要给容器组件传递store,这样不太方便,所以:我们可以在index.js入口文件里引入react-redux里的一个API——Provider

把所有容器组件都需要的store交给Provider,Provider会自动分析整个项目里所有的容器组件,把store传给每一个需要store的容器组件。

index.js:

import React from 'react';
import ReactDOM from 'react-dom/client'
import App from './App'
import store from './redux/store'
import { Provider } from 'react-redux'

// 创建虚拟DOM
const root = ReactDOM.createRoot(document.getElementById('root'))
// 渲染虚拟DOM到页面
root.render(
  <React.StrictMode>
    {/* 检查App组件以及子组件里的一些代码是否有不合理的地方 */}
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
)

⭐优化3:整合UI组件与容器组件

前面两个优化,我们分别从代码层面和API层面进行了优化。在这里,我们将在文件层面对UI组件和容器组件进行优化。

由于我们学习了react-redux库,要求为组件分别写成UI组件和容器组件。那么如果在整个应用中,有20个组件需要和redux打交道,那么我们就需要写40个组件…可想而知,这样写是不行的,我们可以作出一些优化:

可以将UI组件和容器组件整合在同一个文件夹里。

在这里插入图片描述

/src/containers/Count/index.jsx:

import React, { Component } from 'react'
// 引入action
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/count_action'
// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'

// 定义UI组件
class Count extends Component {
  // 加法
  increment = () => {
    const { value } = this.selectNumber
    this.props.jia(value * 1)
  }

  // 减法
  decrement = () => {
    const { value } = this.selectNumber
    this.props.jian(value * 1)
  }

  // 奇数再加
  incrementIfOdd = () => {
    const { value } = this.selectNumber
    if (this.props.count % 2 !== 0) {
      this.props.jia(value * 1)
    }
  }

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    this.props.jiaAsync(value * 1, 500)
  }

  render() {
    return (
      <div>
        <h1>当前求和为:{this.props.count}</h1>
        <select ref={c => this.selectNumber = c}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;
        <button onClick={this.increment}>+</button>&nbsp;
        <button onClick={this.decrement}>-</button>&nbsp;
        <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
        <button onClick={this.incrementAsync}>异步加</button>
      </div>
    )
  }
}

//使用connect()()创建并暴露一个Count的容器组件
export default connect(
  state => ({ count: state }),
  // mapDispatchToProps的简写
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }
)(Count)

⛳求和案例_react-redux优化总结

1️⃣ 容器组件和UI组件整合成一个文件

2️⃣ 无需自己给容器组件传递store,给 < < <App/>包裹一个 < < <Provider store={store}>即可。

3️⃣ 使用了react-redux后也不用再自己监测redux中状态的改变了,容器组件可以自动完成这个工作。

4️⃣ mapDispatchToProps也可以简单的写成一个对象。

5️⃣ 一个组件要和redux“打交道”要经过哪几步?

  • 定义好UI组件—不暴露

  • 引入connect生成一个容器组件,并暴露,写法如下:

    connect(
      state => ({key:value}), //映射状态
      {key:xxxxAction}  //映射操作状态的方法
    )(UI组件)
    
  • 在UI组件中通过this.props.xxxxxx读取和操作状态

今天的分享就到这里啦✨ textcolor{red}{今天的分享就到这里啦✨} 今天的分享就到这里啦

原创不易,还希望各位大佬支持一下 textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

🤞 点赞,你的认可是我创作的动力! textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! textcolor{green}{收藏,你的青睐是我努力的方向!}