第三十五章 多个组件状态数据共享

news2024/11/19 6:15:41

之前,我们的求和案例只是一个组件,属于是自己玩自己,接下来我们通过多个组件,通过redux实现它们之间的数据互通。

步骤1:更改项目目录结构

src
|--containers
|	|--Count
|--redux
|	|--actions
|		|--count.js
|	|--reducers
|		|--count.js
|	|--constant.js
|	|--store.js
|--App.jsx
|--index.js

由于我们现在要实现多个组件的状态共享,需要划分更细致的文件分类,以供我们更好的维护项目。

  • 将原来的count_action.js=变为=> redux/actions/count.js
  • 将原来的count_reducer.js=变为=> redux/reducers/count.js
  • 其他文件相应的导入路径也要做相应的修改,这里不在赘述。

步骤2:新建一个Person组件

文件:src/containers/Person/index.jsx

import React, { Component } from 'react'
import {nanoid} from 'nanoid'

export default class Person extends Component {

  addPerson = () => {
    const { nameNode, ageNode } = this
    const person = {
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    console.log(person)
  }

  render() {
    return (
      <div>
        <h1>Person组件,上方组件求和为:{this.props.sum}</h1>
        <input type="text" placeholder='请输入姓名' ref={c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={c => this.ageNode = c} />&nbsp;
        <button onClick={this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          <li>姓名1--年龄</li>
        </ul>
      </div>
    )
  }
}

然后引入到App组件里面

import React, { Component } from 'react'
// 引入Count的容器组件
import Count from './containers/Count'
import Person from './containers/Person'

export default class App extends Component {
  render() {
    return (
      <div>
        <Count/>
        <hr/>
        <Person/>
      </div>
    )
  }
}

效果如下:

在这里插入图片描述


步骤3:编写Person组件相关的redux文件

(1). 新增常量类型:ADD_PERSON

// src/redux/constant.js
// 该模块是用于定义action对象的type类型的常量值
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
export const ADD_PERSON = 'add_person'

(2). 新增person的action文件

// src/redux/actions/person.js
import { ADD_PERSON } from '../constant'
// 添加人信息的action
export const createAddPersonAction = personObj => ({type: ADD_PERSON, data:personObj})

(3). 新增person的reducer文件

// src/redux/reducers/person.js
import {ADD_PERSON} from '../constant'

const initData = [{id:'001',name:'tom',age:18}]
export default function personReducer (preState = initData, action) {
  // 获取type和data
  const {type,data} = action

  switch (type) {
    case ADD_PERSON:
      return [data,...preState]
  
    default:
      return preState
  }
}

(4). 融合Person的容器组件

import React, { Component } from 'react'
import {nanoid} from 'nanoid'
import {connect} from 'react-redux'
import {createAddPersonAction} from '../../redux/actions/person'

class Person extends Component {

  addPerson = () => {
    const { nameNode, ageNode } = this
    const person = {
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    console.log(person)
  }

  render() {
    return (
      <div>
        <h1>Person组件</h1>
        <input type="text" placeholder='请输入姓名' ref={c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={c => this.ageNode = c} />&nbsp;
        <button onClick={this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          <li>姓名1--年龄</li>
        </ul>
      </div>
    )
  }
}

export default connect(
  state => ({peoList:state}), // 映射状态
  {} // 映射操作状态的方法
)(Person)

至此,我们对Person组件的redux相关代码已经七七八八了,但是现在并不起作用,因为我们的store并没有使用到personreducer里面的逻辑。


步骤4:整改store文件内容

// 引入createStore,专门用于创建redux中最为核心的store对象
import { createStore , applyMiddleware } from 'redux'
import countReducer from './reducers/count'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'

export default createStore(countReducer,applyMiddleware(thunk))


根据代码,我们知道这里没有引入Person相关的reducer,那我们该如何使用呢?

答案是:引入一个新的API合并多个reducer===>combineReducers

combineReducers是一种常用的组合Reducer的方法,它可以使代码更加简洁和易于维护。

// 引入createStore,专门用于创建redux中最为核心的store对象
import { createStore , applyMiddleware, combineReducers } from 'redux'
import countReducer from './reducers/count'
import personReducer from './reducers/person'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'

const allReducer = combineReducers({
  sum: countReducer,
  peoples: personReducer
})
export default createStore(allReducer,applyMiddleware(thunk))

以上就是我们修改后的完整版的store文件了,这里我们使用combineReducers这个APICount组件和Person组件的reducer进行了合并,形成了一个新的allReducer将它传递给createStore这个API


步骤5:在Person组件里面将数据存入redux

import React, { Component } from 'react'
import {nanoid} from 'nanoid'
import {connect} from 'react-redux'
import {createAddPersonAction} from '../../redux/actions/person'

class Person extends Component {

  addPerson = () => {
    const { nameNode, ageNode } = this
    const person = {
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    // console.log(person)
    this.props.addPeople(person)
  }

  render() {
    return (
      <div>
        <h1>Person组件</h1>
        <input type="text" placeholder='请输入姓名' ref={c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={c => this.ageNode = c} />&nbsp;
        <button onClick={this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          {
            this.props.peoList.map((p)=>{
              return <li key={p.id}>{p.name}--{p.age}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

export default connect(
  state => ({peoList:state.peoples}), // 映射状态
  {addPeople:createAddPersonAction} // 映射操作状态的方法
)(Person)

查看效果:
在这里插入图片描述


步骤6:两个组件相互引入redux里面是状态数据

文件:Person/index.jsx

import React, { Component } from 'react'
import {nanoid} from 'nanoid'
import {connect} from 'react-redux'
import {createAddPersonAction} from '../../redux/actions/person'

class Person extends Component {

  addPerson = () => {
    const { nameNode, ageNode } = this
    const person = {
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    // console.log(person)
    this.props.addPeople(person)
  }

  render() {
    return (
      <div>
        <h1>Person组件,上方组件求和为:{this.props.sum} </h1>
        <input type="text" placeholder='请输入姓名' ref={c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={c => this.ageNode = c} />&nbsp;
        <button onClick={this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          {
            this.props.peoList.map((p)=>{
              return <li key={p.id}>{p.name}--{p.age}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

export default connect(
  state => ({peoList:state.peoples,sum:state.sum}), // 映射状态
  {addPeople:createAddPersonAction} // 映射操作状态的方法
)(Person)

文件:Count/index.jsx

// 引入action
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/actions/count'

// 引入react-redux中的connect用于连接UI组件和容器组件
import { connect } from 'react-redux'
import React, { Component } from 'react'

class Count extends Component {

  increment = () => {
    // 普通加
    // 1、获取用户选择的值
    const { value } = this.selectNumber
    this.props.jia(value*1)
  }

  decrement = () => {
    // 普通减
    // 1、获取用户选择的值
    const { value } = this.selectNumber
    this.props.jian(value*1)
  }

  incrementIfOdd = () => {
    // 当前求和为奇数为
    // 1、获取用户选择的值
    const { value } = this.selectNumber
    if (this.props.count %2 !== 0) {
      this.props.jia(value*1)
    }
  }

  incrementAsync = () => {
    // 异步加
    // 1、获取用户选择的值
    const { value } = this.selectNumber
    this.props.jiaAsync(value*1,500)
  }

  render() {
    return (
      <div>
        <h1>当前求和为:{this.props.count},下方组件人数为{this.props.peoLens}</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>&nbsp;
      </div>
    )
  }
}


// 创建并暴露一个容器组件
export default connect(
  state => ({count: state.sum, peoLens: state.peoples.length}),
  {
    jia:createIncrementAction,
    jian:createDecrementAction,
    jiaAsync:createIncrementAsyncAction
  }
  )(Count)

整体效果:

在这里插入图片描述


总结

(1). 定义一个Person组件,和Count组件通过redux共享数据

(2). 为Person组件编写reduceraction,配置constant常量

(3). 重点:PersonreducerCountReducer要使用combineReducer进行合并,合并后的总状态是一个对象!

(4). 交给store的是总reducer,最后注意在组件取出状态的时候,记得是对应的keyvalue,要“取到位”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/543233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

内网渗透(七十八)之域权限维持之ACL滥用(下)

ACL滥用(下) 7、GenericAll 权限 应用于组 再来看看GenericAll 权限 应用于组如何进行权限维持。 由于用户hack是普通的域用户,因此他没有往Domain Admins 组添加用户的权限,如图所示,以用户hack 身份往Domain Admins 组中添加用户,可以看到,添加用户失败。 现在我们…

目标检测,将voc格式转化为coco格式详细过程

在目标检测方法研究中&#xff0c;数据集的格式至关重要&#xff0c;为了减小模型的训练时长&#xff0c;需要现在小数据集进行模型研究&#xff0c;从而需要将VOC数据集转化为coco格式。下面一步一步来看&#xff1a; 1. 下载VOC数据集 Pascal VOC&#xff0c;即Pattern Ana…

windows2003系统SSL证书单站点部署https

本文将讲解&#xff0c;在windows 2003操作系统下&#xff0c;IIS 6 环境的服务器ssl证书安装教程。 安装前&#xff0c;请准备好SSL证书&#xff0c;没有的话&#xff0c;可以点这里申请SSL证书>>> 部署前请退出服务器内安装的杀毒软件&#xff08;360、金山、安全…

Linux 安装Qt6 教程及错误解决

在Linux环境&#xff0c;通常为Ubuntu&#xff0c;安装Qt开发环境&#xff0c;与Windows安装相比&#xff0c;还是稍显繁琐&#xff0c;需要多做几个步骤。 这里的Ubuntu版本采用的是ubuntu-22.04.2-desktop-amd64&#xff0c;所以&#xff0c;比旧版本会少很多坑&#xff0c;…

链表题目强化练

目录 前言 两数相加 删除链表的倒数第N个结点 环形链表 相交链表 合并 K 个升序链表 复制带随机指针的链表 前言 初学者在做链表的题目时有一个特点&#xff0c;就是每看一个链表的题都觉得很简单&#xff0c;但真正到了扣代码的时候不是这卡一块就是那卡一块。这是因为…

No module named PyQt5

背景&#xff1a;将Python文件转成APP&#xff0c;在编辑器中运行没有问题&#xff0c;一使用pyinstaller转成app就报错了 尝试了各种网上的解法都无效&#xff0c;最后是GPT4解决的 Q&#xff1a; 我遇到一个奇怪的问题&#xff0c;我在python文件中&#xff0c;引用了pyqt5…

Android Termux安装MySQL数据库 | 公网安全远程连接【cpolar内网穿透】

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

【数据结构与算法】常见排序算法

文章目录 概述1、冒泡排序&#xff08;Bubble Sort&#xff09;1.1 步骤1.2 动图演示1.3 java代码实现 2、选择排序&#xff08;Selection Sort&#xff09;2.1 步骤2.2 动图演示2.3 java代码实现 3、插入排序&#xff08;Insertion Sort&#xff09;3.1 步骤3.2 动图演示3.3 j…

测试-用例篇

软件测试的生命周期 需求分析 - 测试计划 - 测试设计、测试开发 - 测试执行 - 测试评估 测试用例要素 测试环境、操作步骤、测试数据、预期结果 测试用例的要素没有执行结果。 测试用例要素不需要执行结果&#xff0c;因为执行结果需要执行完测试用例才会知道&#xff0c;没…

代码随想录算法训练营day45 | 70. 爬楼梯 (进阶),322. 零钱兑换,279.完全平方数

代码随想录算法训练营day45 | 70. 爬楼梯 &#xff08;进阶&#xff09;&#xff0c;322. 零钱兑换&#xff0c;279.完全平方数 70. 爬楼梯 &#xff08;进阶&#xff09;解法一&#xff1a;动态规划 322. 零钱兑换解法一&#xff1a;动态规划 279.完全平方数解法一&#xff1…

秒懂算法 | 共识算法之Raft算法模拟数

01、Leader选举 存在A、B、C三个成员组成的Raft集群&#xff0c;刚启动时&#xff0c;每个成员都处于Follower状态&#xff0c;其中&#xff0c;成员A心跳超时为110ms&#xff0c;成员B心跳超时为150ms&#xff0c;成员C心跳超时为130ms&#xff0c;其他相关信息如图1所示。 ■…

2024王道数据结构考研丨第三章:栈和队列

2024王道数据结构考研笔记专栏将持续更新&#xff0c;欢迎 点此 收藏&#xff0c;共同交流学习… 文章目录 第三章&#xff1a;栈和队列3.1栈&#xff08;stack&#xff09;3.1.1栈的基本概念3.1.2 栈的顺序存储3.1.3栈的链式存储 3.2队列&#xff08;Queue&#xff09;3.2.1队…

【点云抽稀】一种基于均匀分布随机数的点云抽稀算法

文章目录 1. 背景2. 原理3. 实现3.1 定义Utils类3.2 加入预定义宏&#xff0c;确定层级3.3 函数实现 1. 背景 在大数据点云的存储中&#xff0c;常常要进行空间分区&#xff0c;一般的策略是构建四叉树或者八叉树。在构建树的过程中&#xff0c;一个不可避免的点就是点云的快速…

Text, Shapes, Colors 的使用

1. Text 的使用 // 多行文本 // Hello, World! This is the Swiftful Thinking Bootcamp. I am really enjoying this course and learning alot.// .lowercased() 文字小写 .uppercased() 文字大写 capitalized: 以单词形式显示 Text("Hello, World!".capitalized)…

test123

import matplotlib.pyplot as plt import pandas as pd # 从Power BI中获取输入数据 data pd.DataFrame({ Country: [USA, Canada, UK, Germany, France], Population: [328, 38, 66, 83, 67] }) # 使用Matplotlib绘制图表 plt.bar(data[Country], data[Population]…

Sentinel的另外三种流控模式(附代码详细介绍)

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;在一家满意的公司实习。本篇文章将详细介绍Sentinel的其他三种流控模式&#xff0c;后续文章将详细介绍Sentinel的其他知识。 如果文章有什么需要改进的地方还请大佬不吝赐教&#x1f44f;&#…

轻量应用服务器如何选择之阿里云和腾讯云PK哪个好?

阿里云和腾讯云都有轻量应用服务器&#xff0c;轻量服务器是一种轻量级开箱即用的云服务器&#xff0c;适合小型网站、博客或测试等单机应用&#xff0c;那么问题来了&#xff0c;轻量应用服务器到底是阿里云好还是腾讯云好&#xff1f;阿腾云来详细对比下阿里云轻量应用服务器…

find命令的结果顺序

文章目录 1. 目的2. 准备&#xff1a; 克隆 doxygen 源码3. ubuntu22.04 结果4. ubuntu16.04 结果5. git bash 结果6. 三路比较7. 保持一样的结果&#xff1a; 用自然排序8. References 1. 目的 在研读 doxygen 源码时&#xff0c; 在不同电脑、不同操作系统上使用了 find 命令…

vue2中provide/inject的使用

一般来说&#xff0c;组件之间有以下几种关系&#xff1a; A-B、A-C、B-D、B-E、C-F都是父子关系&#xff0c;B-C、D-E-F是兄弟关系&#xff0c;A-D、A-E、A-F是祖先与孙子关系。 vue2中provide/inject这对选项需要一起使用&#xff0c;以允许一个祖先组件向其所有子孙后代注…

私有化部署即时通讯工具能为企业提升工作沟通效率吗?

在疫情的影响下&#xff0c;越来越多的企业开始采用私有化部署的方式部署即时通讯工具&#xff0c;以提升工作沟通效率。私有化部署的即时通讯工具&#xff0c;能够为企业提供完善的人员管理、安全保障、灵活便捷等优势&#xff0c;帮助企业更好地管理人员、团队协作以及工作沟…