React学习27(react-redux多组件共享数据)

news2024/9/25 11:21:33

项目结构

 准备工作

1)定义一个person组件,和count组件通过redux共享数据

2)为person组件编写:reducer ,action和contant常量

3)重点:Person的reducer和Count的reducer要用combineReducers进行合并,合并后的总状态

是 一个对象

4)交给store的是总的reducer,最后注意在组件中取出状态的时候,记得取到位

代码展示

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App.jsx'
import store from './redux/store'//为provider服务
import {Provider} from 'react-redux'

ReactDOM.render(
<Provider store= {store}>
  <App/>
</Provider>,
document.getElementById('root')
)

// 检测redeux中状态的改变,若redux的状态发生了改变,那么重新渲染App组件
//使用react-redux创建容器组件后,react-redux可以自己实现检测state中状态的改变,所以可以删除
//以下代码
// store.subscribe(() => {
//   ReactDOM.render(<App/>,document.getElementById('root'))
// })

App.jsx

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

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

redux-store.js

/*
  该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/

//引入createStore,专门用于创建redux中最为核心的store对象,applyMiddleware用于支持
//异步action的中间件
//combineReducers用于合并多个reducer
import {createStore,applyMiddleware,combineReducers} from 'redux'

//引入为Count组件服务的reducer
import countReducer from './reducers/count'

//引入为Person组件服务的reducer
import personReducer from './reducers/person'

//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'

//汇总所有的reducer变为一个总的reducers
const allReducer = combineReducers({
  he:countReducer,
  rens:personReducer
})

export default createStore(allReducer, applyMiddleware(thunk))

redux-content.js

/*
  该文件是用于定义action对象中的type类型的常量值
  目的只有一个:防止程序员在编码的同时单次写错
*/

export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
export const ADD_PERSON = 'add_person'

redux-actions-count.jsx

/*
  该文件专门为count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "../constant"
//完整写法
// function createIncrementAction(data) {
//   return {type:'increment', data }
// }
//简写形式
//同步action,就是值action的返回值是Object类型的一般对象
export const createIncrementAction = data =>( {type:INCREMENT, data })

//完整写法
// function createDecrementAction(data) {
//   return {type:'decrement', data}
// }
export const createDecrementAction = data =>( {type: DECREMENT, data })

//异步action,就是值action的返回值是函数,异步action一般都会调用同步action
//异步action不是必须要用的
export const createIncrementAsyncAction = (data, time) =>{
  return (dispatch) => {
    setTimeout(() => {
      dispatch(createIncrementAction(data))
    },time)
  }
}

redux-actions-person.js

import {ADD_PERSON} from '../constant'

//创建增加一个人的action对象
export const creatAddPersonAction = personObj => ({type:ADD_PERSON, data:personObj})

redux-reducers-count.js

/*
  1.该文件用于创建一个为count组件服务的reducer,reducer的本质就是一个函数
  2.reducer函数会接到两个参数,分别是之前的state(状态)和action(动作对象)
*/
import { INCREMENT, DECREMENT } from "../constant";

const initState = 0
export default function countReducer(preState=initState, action) {
  console.log(preState, action);
  //从action对象中获取type, data
  const {type, data} = action
  //根据type类型决定如何加工
  switch (type) {
    case INCREMENT:// 如果是加
     return preState + data
    case DECREMENT:// 如果是减
      return preState - data
    default:
      return preState
  }
}

redux-reducers-person.js

import { ADD_PERSON } from "../constant"

//初始化人的列表
const initState = [{id:'001',name:'tom', age:18}]

export default function personReducer(preState=initState, action) {
  const {type,data} = action
  switch(type) {
    case ADD_PERSON:
      return [data, ...preState]// 若是添加一个人
    default:
      return preState
  }
}

containers-count-index.jsx

//引入CountUI组件
// import CountUI from '../../compoents/Count'

import React, { Component } from 'react'

//引入connect用于连接UI组件和redux
import {connect} from 'react-redux'
//引入action
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/actions/count'

//定义UI组件
class Count extends Component {
  state = {carName:'奔驰c63'}//  把状态交给reducer之后组件也可以有自己独用的状态


  increment = () => {
    const {value} = this.selectNum
    this.props.jia(value*1)

  }
  decrement = () => {
    const {value} = this.selectNum
    this.props.jian(value*1)
  }
  incrementOdd = () => {
    const {value} = this.selectNum
    if(this.props.count % 2 !== 0) {
      this.props.jia(value*1)
    }
  }
  incrementWait = () => {
    const {value} = this.selectNum
    this.props.jiaAsync(value*1,400)
  }
  render() {
    console.log('UI组件接收到的props是:',this.props);
    return (
      <div>
        <h2>我是Count组件,下方组件总人数是{this.props.renshu}</h2>
        <h3>当前求和为:{this.props.count}</h3>
        <select ref={c => {this.selectNum = 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.incrementOdd}>当前求和为奇数再加</button>&nbsp;
        <button onClick= {this.incrementWait}>等一等再加</button>
      </div>
    )
  }
}

//使用connect()()创建并暴露一个Count容器组件
export default connect(
  state => ( {count:state.he,renshu:state.rens.length}), 
  //mapDispatchToProps的一般写法
  // dispatch => ({
  //   jia:number => dispatch(createIncrementAction(number)),
  //   jian:number => dispatch(createDecrementAction(number)),
  //   jiaAsync:(number,time) =>dispatch(createIncrementAsyncAction(number,time)) 
  // })

   //mapDispatchToProps的简写,dispatch由react-redux来完成,程序员工作中用这种方法
   {
    jia:createIncrementAction,
    jian:createDecrementAction,
    jiaAsync:createIncrementAsyncAction
   }
  )(Count)

containers-Person-index.jsx

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

class Person extends Component {
  addPerson = () => {
    const name = this.nameNode.value
    const age = this.ageNode.value
    const personObj = {id:nanoid(), name, age}
    this.props.jiayiren(personObj)
    this.nameNode.value = ''
    this.ageNode.value = ''
  }
  render() {
    return (
      <div>
        <h2>我是person组件,上方组件求和为{this.props.he}</h2>
        <input ref={c => this.nameNode = c} type="text" placeholder="请输入姓名"/>&nbsp;
        <input ref={c => this.ageNode = c} type="text" placeholder="请输入年龄"/>&nbsp;
        <button onClick= {this.addPerson}>添加</button>
        <ul>
         {
            this.props.yiduiren.map((p) => {
              return <li key={p.id}>{p.name}--{p.age}</li>
            })
         }
        </ul>
      </div>
    )
  }
}

export default connect(
  state => ({yiduiren:state.rens,he:state.he}),// 映射状态
  {jiayiren:creatAddPersonAction}//映射操作状态的方法
)(Person)

纯函数

A、一类特别的函数:只要是同样的输入(实参),必定得到同样的输出(返回)

B、必须遵循以下的一些约束

        不得改写参数数据;

        不会产生任何副作用,例如:网络请求,输入和输出设备;

        不能调用Date.now()或者是Math.random()等不纯的方法

C、redux的reducer函数必须是一个纯函数

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

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

相关文章

深度学习-优化器

优化器 文章目录优化器1. 引言1. SGD1.1 vanilla SGD1.2 SGD with Momentum1.3 SGD with Nesterov Acceleration2. AdaGrad3. RMSProp4. AdaDelta5. Adam优化器选择出处1. 引言 优化算法可以分成一阶优化和二阶优化算法&#xff0c;其中一阶优化就是指的梯度算法及其变种&#…

Linux——vi,vim的使用

三种模式 正常模式 以vi或vim打开一个档案就直接进入一般模式了(这是默认的模式)。在这个模式中&#xff0c;你可以使用 【上下左右】 按键来移动光标&#xff0c;你可以使用 【删除字符】或 【删除整行】来处理档案内容&#xff0c;也可以使用 【复制&#xff0c;粘贴】来处…

3D激光里程计其三:点云畸变补偿

3D激光里程计其三&#xff1a;点云畸变补偿1. 产生原因2. 补偿方法Reference: 深蓝学院-多传感器融合 1. 产生原因 一帧点云&#xff1a;通常指雷达内部旋转一周扫描得到的点的集合。 优点&#xff1a;有足够数量的点云才能进行匹配&#xff0c;且一周正好是周围环境的完整采…

认识Java中的异常处理

文章目录Java异常处理异常体系的介绍常见运行时异常常见编译时异常Java异常处理 异常体系的介绍 什么事异常处理? 异常是程序在“编译”或者“执行”的过程中可能出现的问题&#xff0c;比如: 数组索引越界、空指针异常、 日期格式化异常&#xff0c;等… 注意&#xff1a;语…

常用损失函数

常见损失函数 文章目录常见损失函数引言回归1. 均方差2.平均绝对误差(MAE)3. 均方根误差(RMSE)4. 交叉熵分类二分类多分类引言 无论在机器学习还是深度领域中,损失函数都是一个非常重要的知识点。损失函数&#xff08;Loss Function&#xff09;是用来估量模型的预测值 f(x) 与…

Eslint 8.23 Flat Config 新配置迁移升级指南

前言 直入正题&#xff0c;eslint 目前为止的配置文件格式&#xff08; 如 .eslintrc.js &#xff09; 存在很多无法避免的历史问题&#xff1a; 配置格式混乱&#xff0c;层层不明确的继承&#xff0c;不易理解。 插件配置时不支持实体运用&#xff08;不能传 function / ob…

学完框架后的反思—为什么要使用框架?

学习前端也有一定的时间了,最近在网上看到了一个问题让我反思了很久——为什么要使用前端框架? 我发现自己当初学习框架时并没有想那么多,只是看中了其在业界企业的应用,大部分公司开发页面基本上都是使用框架进行开发的,而最为被大厂广泛接受的就是 React 框架,所以我当…

二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮 DPPE-PEG-N3简介,可用于药物传递、基因转染和生物分子修饰。

二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮 DPPE-PEG-N3 中文名称&#xff1a;二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮基 英文名称&#xff1a;DPPE-PEG-N3 英文别名&#xff1a; 1,2-dipalmitoyl-sn-glycero-3-phosphoethanolamine-PEG-Azide 分子量&#xff08;PEG&#xff09;&a…

Linux——任务调度

at定时任务 基本介绍 at命令是一次性定时计划任务&#xff0c;at地守护线程atd会以后台模式运行&#xff0c;检查作业队列来运行默认情况下&#xff0c;atd守护进程没60秒检查作业队列&#xff0c;有作业时&#xff0c;会检查作业运行时间&#xff0c;如果时间于当前时间匹配…

Dubbo 1 分布式系统中的相关概念 1.2 集群和 分布式

Dubbo 【黑马程序员Dubbo快速入门&#xff0c;Java分布式框架dubbo教程】 1 分布式系统中的相关概念 文章目录Dubbo1 分布式系统中的相关概念1.2 集群和 分布式1.2.1 集群和分布式1.2.2 集群和分布式 【互联网 中】1.2 集群和 分布式 1.2.1 集群和分布式 集群&#xff1a;很…

使用synchornized和ReentrantLock来解决并发错误

文章目录什么是并发错误&#xff1f;并发错误是如何产生的&#xff1f;演示并发错误如何解决并发错误使用synchornized解决并发错误使用ReentrantLock解决并发错误什么是并发错误&#xff1f; 多个线程共享操作同一个对象的时候&#xff0c;线程体当中连续的多行操作未必能够连…

下个文档还要马内?还好我会Python,教大家来一手强制复制粘贴

前因后果 公司有人阳了&#xff0c;今天在家上班&#xff0c;突然小姨子就问我有没有baidu文库会员&#xff0c;想下载点东西&#xff0c;我心想这还要会员&#xff1f;用Python不是分分钟的事情&#xff01; 然后我非常自信的告诉她不用会员随便下载&#xff0c;结果她顺势想…

10两级电力市场环境下计及风险的省间交易商最优购电模型

参考文章&#xff1a; 两级电力市场环境下计及风险的省间交易商最优购电模型—郭立邦&#xff08;电网技术2019&#xff09; 主要内容&#xff1a; 为进一步推动电力市场建设&#xff0c;促进电力资源大范围优化配置&#xff0c;我国正逐步建成包含省间与省内电力交易的两级…

齿轮魔方、五阶齿轮魔方

齿轮魔方 1&#xff0c;魔方三要素 &#xff08;1&#xff09;组成部件 部件和三阶魔方完全对应&#xff0c;但每个棱块的朝向不止2种&#xff0c;而是有6种。 &#xff08;2&#xff09;可执行操作 只有3种操作&#xff0c;即上下层同时旋转180度、左右180度、前后180度。…

一文助你快速理解Cookie,Session,Token的区别

目录 一、Cookie简介 1.1.cookie定义 1.2.cookie鉴权原理 1.3.cookie的分类 二、Session简介 2.1.session的定义 2.2.session会话机制 2.3.Session 的缺点 三、cookie与session区别 3.1.存储位置 3.2.安全性 3.3.占用服务器资源 3.4.存储空间 3.5.存储类型 3.6.…

编程入门宝典,刚开始学习编程新手必看的5点建议!

编程就像围城&#xff0c;城里的人想出去&#xff0c;城外的人想进来。 对于零基础的小白&#xff0c;要杀入代码的战场需要准备好哪些东西呢?最帅的萌宝在此给大家分享5点建议。 1、选择编程语言 编程首要还是选择好适合自己的语言。 编程语言有&#xff1a;C/C、java、VB、P…

零基础学Python:编程规范

1. 注释 python注释也有自己的规范&#xff0c;在文章中会介绍到。注释可以起到一个备注的作用&#xff0c;团队合作的时候&#xff0c;个人编写的代码经常会被多人调用&#xff0c;为了让别人能更容易理解代码的通途&#xff0c;使用注释是非常有效的。 在说规范之前我们有必…

微服务综合部署——SpringBoot项目制作Docker镜像注册在Zookeeper并利用K8S技术部署

一、如果你要从头开发一个基于微服务架构的项目&#xff0c;项目中的服务最终要部署在k8s管理的镜像环境中&#xff0c;你认为应如何创建项目&#xff1f;与本次实验过程相比&#xff0c;哪些改进可以让开发更加合理高效&#xff1f; 第一步&#xff1a;搭建项目并制作合适的j…

回溯算法总结

目录介绍伪代码例题&#xff1a;解释&#xff1a;回溯算法中的优化去重伪代码剪枝常见题型子集例题全排列例题参考资料介绍 递归(DFS)是一个劲的往某一个方向搜索&#xff0c;而回溯算法建立在 DFS 基础之上的&#xff0c;但不同的是在搜索过程中&#xff0c;达到结束条件后&am…

SAP ABAP 扫描 ABAP 源代码(RS_ABAP_SOURCE_SCAN)

SAP ABAP 扫描 ABAP 源代码&#xff08;RS_ABAP_SOURCE_SCAN&#xff09; 引言&#xff1a; RS_ABAP_SOURCE_SCAN 是一个 SAP 标准 ABAP 报表程序&#xff0c;通过输入字符串文本&#xff0c;扫描 ABAP 源代码&#xff0c;列示查找字符串在 ABAP 源代码中出现的位置清单。本文…