react-redux集中式状态管理及基本使用与优化

目录
  • 1、react-redux
  • 2、连接容器组件与UI组件
  • 3、react-redux基本使用
  • 优化1、简写mapState和mapDispatch两个映射方法
  • 优化2、Provider组件的使用
  • 优化3、整合UI组件与容器组件
  • 优化总结

1、react-redux

react-redux把组件分为两类,一类叫做UI组件,一类叫做容器组件;

UI组件的外侧都要包裹一个容器组件。

注意️:本文使用的示例为之前的文章中的示例。在之前的文章中已经做过了介绍,在本文就不再阐述。

建议阅读顺序是:
【redux工作流程】
【redux异步action】
再到本文

2、连接容器组件与UI组件

UI组件存放在components文件夹中,我们可以在src目录下新建文件夹containers,专门用于存放容器组件

例如:Count组件的容器组件:/src/containers/Count/index.jsx

/*
  该组件是Count组件这个UI组件的容器组件
 */
// 引入Count组件的UI组件
import CountUI from '../../components/Count'
// 引入connect用于连接UI组件与容器组件
import { connect } from 'react-redux'

//创建并暴露一个Count的容器组件,connect()()的含义是:调用connect()这个函数返回的函数
export default connect()(CountUI)

代码解释:

引入CountUI,为Count组件的UI组件,从原理图中来看,该组件是Count容器组件的子组件。

引入connect函数,用于连接UI组件与容器组件;

我们从原理图中可以看出,redux要想工作,必须要连接UI组件与容器组件,还必须连接容器组件与store。

那么我们在容器组件中,使用connect()()的方法连接了UI组件

【connect()()的含义:调用connect()这个函数的返回值,返回值本身是一个函数,也就是调用返回的函数】

现在还需要让容器组件与store建立起连接;

怎么让容器组件与store建立起连接呢?

我们之前在App组件中一直都是渲染Count的UI组件的,但是我们现在引入了Count的容器组件(为Count的UI组件的父组件),那么我们可以直接在App组件中直接渲染Count组件的容器组件:

// 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>
    )
  }
}

重点️在于,

在渲染Count组件的容器组件时,通过组件的props属性,将store传入Count组件的容器组件,从而实现容器组件与store建立起连接。

3、react-redux基本使用

现在我们已经把UI组件与容器组件建立起连接了,并且将容器组件与store也建立起连接了,那么我们接下来一起来探索react-redux是怎么工作,如何使用的呢?

从流程图可以看出,我们需要向UI组件传递state(状态)和dispatch(操作状态的方法)。

但是我们在UI组件的父组件,也就是Count的容器组件中,并没有以组件标签()的形式去渲染子组件

而是通过react-redux提供的connect方法将父子组件建立起的联系,我们就需要通过connect方法传递props。

我们之前知道,我们在调用connect方法返回的函数时需要传递UI组件作为参数,以将容器组件与UI组件连接起来,也就是

connect()(CountUI)

而传递props时,我们需要在调用connect方法时直接传入两个参数(也就是connect的第一个括号内的参数),并且这两个参数都是函数形式的参数。具体看代码吧~

connect(mapStateToProps, mapDispatchToProps)(CountUI)

说明:第一个函数参数mapStateToProps作用是将存放在store中的状态映射给UI组件的props;

第二个函数参数mapDispatchToProps作用是将操作数据的方法映射给UI组件的props;

其实也就对应图中的

具体实现如下:

/*
  该组件是Count组件这个UI组件的容器组件
 */
import CountUI from '../../components/Count'
import { connect } from 'react-redux'
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/count_action_creator'
/*
  1.mapStateToProps函数返回的是一个对象;
  2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
  3.mapStateToProps用于传递状态
*/
function mapStateToProps(state) {
  return { count: state }
}

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

//创建并暴露一个Count的容器组件,connect()()的含义是:调用connect()这个函数返回的函数
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

这样一来,Count的UI组件就会接收到传递进来的props,我们可以通过props去渲染状态和操作状态:

/src/components/Count/index.jsx:

渲染状态:

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

操作状态:

// 加法
increment = () => {
  const { value } = this.selectedNumber
  this.props.jia(value * 1)
}
// 减法
decrement = () => {
  const { value } = this.selectedNumber
  this.props.jian(value * 1)
}
// 和为奇数时,加
incrementIfOdd = () => {
  const { value } = this.selectedNumber
  if (this.props.count % 2 !== 0) {
    this.props.jia(value * 1)
  }
}
// 异步加
incrementAsync = () => {
  const { value } = this.selectedNumber
  this.props.jiaAsync(value * 1, 500)
}

react-redux基本使用总结:

明确两个概念:UI组件与容器组件

UI组件:不能使用任何redux的api,只负责页面的呈现、交互等等;

容器组件:负责和redux通信,将结果交给UI组件

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

connect(mapStateToProps, mapDispatchToProps)(CountUI)

mapStateToProps——映射状态,返回值是一个对象;

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

备注:容器组件中的store是靠props传入的,而不是在容器组件中直接引入。

优化1、简写mapState和mapDispatch两个映射方法

原映射方法:

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

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

简写成箭头函数:

const mapStateToProps = state => ({ count: state })

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

当然,这只是在编码的角度对函数进行简化,我们还可以在API的角度,实现mapDispatch更为简洁的写法。

其实mapDispatchToProps还可以是一个对象,在一般写法中,mapDispatchToProps是一个函数,但是可以简写成一个对象。

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

  // mapDispatchToProps的简写——是一个对象
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }

  // mapDispatchToProps一般写法——是一个函数
  /* dispatch => (
    {
      jia: (data) => {
        // 通知redux执行加法
        dispatch(createIncrementAction(data))
      },
      jian: (data) => {
        dispatch(createDecrementAction(data))
      },
      jiaAsync: (data, time) => {
        dispatch(createIncrementAsyncAction(data, time))
      }
    }
  ) */
)(CountUI)

把mapDispatchToProps简写成一个对象的话,react-redux会自动分发,也就是底层自动调用dispatch方法,所以我们在书写代码时并不需要手动调用dispatch方法,在mapDispatchToProps简写成一个对象时可以省略dispatch,这就是属于API层面的优化。

优化2、Provider组件的使用

在前面的连接容器组件和store的讲解中,我们提出:要想连接容器组件和store,就需要在App.jsx中通过props将store传入容器组件中。也就是这样子的:

// 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>
    )
  }
}

现在我们基于react-redux,可以对App组件进行优化:

// App.jsx
import React, { Component } from 'react'
import { Provider } from 'react-redux'
import Count from './containers/Count'
import store from './redux/store'

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

这样一来,哪怕我们需要连接多个容器组件到store,都只需要在渲染组件标签的外围包裹一个< Provider>标签即可。

优化3、整合UI组件与容器组件

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

我们前面在逐步学习实践react-redux时,将容器组件放在containers文件夹中。但是我们发现,如果需要使用redux的UI组件越来越多的话,需要的容器组件也越来越多,到最后可能项目中有20个组件需要使用redux中的状态,那么我们真的就另外创建20个容器组件吗?

Of course not ! Of course not! Ofcoursenot!

其实我们可以将UI组件与容器组件整合在同一个文件内!

/src/containers/Count/index.jsx:

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

// 定义UI组件Count
class Count extends Component {
  // 加法
  increment = () => {
    const { value } = this.selectedNumber
    this.props.jia(value * 1)
  }
  // 减法
  decrement = () => {
    const { value } = this.selectedNumber
    this.props.jian(value * 1)
  }
  // 和为奇数时,加
  incrementIfOdd = () => {
    const { value } = this.selectedNumber
    if (this.props.count % 2 !== 0) {
      this.props.jia(value * 1)
    }
  }
  // 异步加
  incrementAsync = () => {
    const { value } = this.selectedNumber
    this.props.jiaAsync(value * 1, 500)
  }

  render() {
    return (
      <div>
        <h1>当前求和为:{this.props.count}</h1>
        <select ref={currentNode => { this.selectedNumber = currentNode }}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;&nbsp;&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>
    )
  }
}
// 创建并暴露一个Count的容器组件,connect()()的含义是:调用connect()这个函数返回的函数
export default connect(
  state => ({ count: state }),
  // mapDispatchToProps的简写——是一个对象
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }
  // mapDispatchToProps一般写法——是一个函数
)(Count)

如此一来,我们就可以删除/src/components/Count/index.jsx了~

优化总结

容器组件和UI组件整合为同一个文件

无需自己给容器组件传递store,给包裹一个标签,在Provider内传递store即可;

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

mapDispatchToProps也可以简单的写成一个对象;

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

定义好UI组件——不暴露;引入connect生成一个容器组件,并暴露,写法如下:

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

到此这篇关于集中式状态管理<react-redux>基本使用与优化的文章就介绍到这了,更多相关react-redux集中式状态管理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • React状态管理Redux原理与介绍

    目录 一.Redux 二.Redux的组成 2.1 store 2.2 state 2.3 action 2.4 reducer 三.三大原则 3.1 单一数据源 3.2 State只读 3.3 使用纯函数修改State 四.基于Redux的TodoList 五.react-redux 5.1 connect方法 5.2 Provider组件 一.Redux 和vuex一样,redux的出现是为了管理web应用的公共状态. 这些 state 可能包括服务器响应.缓存数据.本地生成尚未持久化到服务

  • React状态管理Redux的使用介绍详解

    目录 1. 简介 2. 核心概念 3. redux工作流 4. 模拟redux工作流程 5. 使用redux 6. react-redux 1. 简介 Redux 是 JavaScript 应用的状态容器(对象),提供可预测的状态管理.可以让你开发出行为稳定可预测的应用,运行于不同的环境(客户端.服务器.原生应用),并且易于测试.Redux 除了和 React 一起用外,还支持其它界面库. 解决的问题:多层级组件间通信问题. 2. 核心概念 单一数据源 整个redux中的数据都是集中管理,存储于

  • react18中react-redux状态管理的实现

    react的状态管理还是挺多的现在流行的有以下五种: Recoil MobX XState Redux Context 今天我们来讲一下react众多状态管理之一的redux,虽然这个我不太喜欢用,但是我觉得简单的状态管理谁都会,但是难的就是程序员的分水岭,所以今天来给大家讲一下redux. 下面我们来讲讲redux的优点: 可以在众多组件中传值,突破react单向数据流的限制 不仅支持react还支持vue等主流框架 当然是好用方便啦 接下来我们讲一下啥时候去使用他 在我们有好多组件,但是组件

  • react-redux集中式状态管理及基本使用与优化

    目录 1.react-redux 2.连接容器组件与UI组件 3.react-redux基本使用 优化1.简写mapState和mapDispatch两个映射方法 优化2.Provider组件的使用 优化3.整合UI组件与容器组件 优化总结 1.react-redux react-redux把组件分为两类,一类叫做UI组件,一类叫做容器组件: UI组件的外侧都要包裹一个容器组件. 注意️:本文使用的示例为之前的文章中的示例.在之前的文章中已经做过了介绍,在本文就不再阐述. 建议阅读顺序是:[re

  • 基于React Hooks的小型状态管理详解

    目录 实现基于 React Hooks 的状态共享 使用感受 本文主要介绍一种基于 React Hooks 的状态共享方案,介绍其实现,并总结一下使用感受,目的是在状态管理方面提供多一种选择方式. 实现基于 React Hooks 的状态共享 React 组件间的状态共享,是一个老生常谈的问题,也有很多解决方案,例如 Redux.MobX 等.这些方案很专业,也经历了时间的考验,但私以为他们不太适合一些不算复杂的项目,反而会引入一些额外的复杂度. 实际上很多时候,我不想定义 mutation 和

  • Vue的状态管理vuex使用方法详解

    引入vuex 当访问数据对象时,一个 Vue 实例只是简单的代理访问.所以,如果有一处需要被多个实例间共享的状态,可以简单地通过维护一份数据来实现共享 const sourceOfTruth = {} const vmA = new Vue({ data: sourceOfTruth }) const vmB = new Vue({ data: sourceOfTruth }) 现在当 sourceOfTruth 发生变化,vmA 和 vmB 都将自动的更新引用它们的视图.子组件们的每个实例也会

  • vue store之状态管理模式的详细介绍

    状态管理 一.状态管理(vuex)简介 uex是专为vue.js应用程序开发的状态管理模式.它采用集中存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.vuex也集成刀vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试.状态快照导入导出等高级调试功能. Vuex 的思想 当我们在页面上点击一个按钮,它会处发(dispatch)一个action, action 随后会执行(commit)一个mutation, mut

  • Mobx实现React 应用的状态管理详解

    目录 MobX 从一个 demo 开始 创建类并将其转化成可观察对象 使用可观察对象 MobX 与 React 集成 在组件中使用可观察对象 1. 访问全局的类实例 2. 通过 props 3. 通过 React Context 4. 在组件中实例化 observable class 并存储它的实例 5. 在组件中调用 observable 方法创建可观察对象 6. 在函数组件中使用 useLocalObservable 让组件具备观察能力 总结 MobX MobX 是一个状态管理库,它会自动收

  • Vuex中状态管理器的使用详解

    目录 一.Vuex是什么? 二.什么时候使用Vuex 三.Vuex的核心概念和API 四.应用举例 五.vuex中各种辅助函数的用法,可以使我们更加方便的运用vuex 一.Vuex是什么? Vuex在Vue项目开发时使用的状态管理工具.简单来说,就是对Vue的应用中多个组件的共享状态进行集中式的管理(读/写) Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取Sta

  • 在react中使用vue的状态管理的方法示例

    我是要介绍一个新的 react 全局共享状态管理器,它和 vue 组件的状态管理一起同工之妙. 马上体验 在 react 状态管理领域,react-redux 可谓是只手遮天了,基于 flux 思想实现,小巧,immutable 的思想让数据变化可控.但 immutable 所带来的编程代价太大了,如果你要更新一个深层结构的对象的某个节点,写作将会是极其麻烦的一件事,而且还保不准会出错.为了保证 immutable,redux 的 reducer 机制让开发者掉光了头发.于是有了类似 dva.r

  • React全局状态管理的三种底层机制探究

    目录 前言 props context state 总结 前言 现代前端框架都是基于组件的方式来开发页面.按照逻辑关系把页面划分为不同的组件,分别开发不同的组件,然后把它们一层层组装起来,把根组件传入 ReactDOM.render 或者 vue 的 $mount 方法中,就会遍历整个组件树渲染成对应的 dom. 组件都支持传递一些参数来定制,也可以在内部保存一些交互状态,并且会在参数和状态变化以后自动的重新渲染对应部分的 dom. 虽然从逻辑上划分成了不同的组件,但它们都是同一个应用的不同部分

随机推荐