React(react18)中组件通信04——redux入门

React(react18)中组件通信04——redux入门

  • 1. 前言
    • 1.1 React中组件通信的其他方式
    • 1.2 介绍redux
      • 1.2.1 参考官网
      • 1.2.2 redux原理图
      • 1.2.3 redux基础介绍
        • 1.2.3.1 action
        • 1.2.3.2 store
        • 1.2.3.3 reducer
    • 1.3 安装redux
  • 2. redux入门例子
  • 3. redux入门例子——优化1(reducer 和 store拆开)
    • 3.1 想要实现的效果
    • 3.2 代码设计
    • 3.3 添加 重新渲染
    • 3.4 附代码
  • 4. redux入门例子——优化2(拆出action)
    • 4.1 关于action的其他说明
    • 4.2 优化——拆出action
    • 4.3 优化——动态加减数字
      • 4.3.1 优化看效果
      • 4.3.2 附代码

1. 前言

1.1 React中组件通信的其他方式

  • React(react18)中组件通信01——props.
  • React(react18)中组件通信02——消息订阅与发布、取消订阅以及卸载组件时取消订阅.
  • React(react18)中组件通信03——简单使用 Context 深层传递参数.

1.2 介绍redux

1.2.1 参考官网

  • 讲解、例子,参考官网,官网地址如下:
    Redux 中文文档——https://www.redux.org.cn/.

1.2.2 redux原理图

  • 原理图,如下:
    在这里插入图片描述
  • 简单解释
    • 要想更新 state 中的数据,你需要发起一个 actionAction 就是一个普通 JavaScript 对象(注意到没,这儿没有任何魔法?)用来描述发生了什么。
    • 强制使用 action 来描述所有变化带来的好处是可以清晰地知道应用中到底发生了什么。如果一些东西改变了,就可以知道为什么变。action 就像是描述发生了什么的指示器。
    • 最终,为了把 action 和 state 串起来,开发一些函数,这就是 reducer。再次地强调,没有任何魔法,reducer 只是一个接收 state 和 action,并返回新的 state 的函数,并且是一个纯函数
    • 而整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。

1.2.3 redux基础介绍

1.2.3.1 action
  • Action 是把数据从应用(这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。
  • Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。
1.2.3.2 store
  • Store 就是把它们联系到一起的对象。Store 有以下职责:
    • 维持应用的 state;
    • 提供 getState() 方法获取 state;
    • 提供 dispatch(action) 方法更新 state;
    • 通过 subscribe(listener) 注册监听器;
    • 通过 subscribe(listener) 返回的函数注销监听器。
  • 强调一下 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合 而不是创建多个 store。
1.2.3.3 reducer
  • Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
  • reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。
  • 整个应用只有一个单一的 reducer 函数:这个函数是传给 createStore 的第一个参数。一个单一的 reducer 最终需要做以下几件事:
    • reducer 第一次被调用的时候,state 的值是 undefined。reducer 需要在 action 传入之前提供一个默认的 state 来处理这种情况。
    • reducer 需要先前的 state 和 dispatch 的 action 来决定需要做什么事。
    • 假设需要更改数据,应该用更新后的数据创建新的对象或数组并返回它们。
    • 如果没有什么更改,应该返回当前存在的 state 本身。

1.3 安装redux

  • 命令如下:
    npm install --save redux
    

2. redux入门例子

  • 直接从官网拷贝的例子,例子地址:
    https://www.redux.org.cn/.
  • 例子如下:
    在这里插入图片描述
    import { createStore } from 'redux';/*** 这是一个 reducer,形式为 (state, action) => state 的纯函数。* 描述了 action 如何把 state 转变成下一个 state。** state 的形式取决于你,可以是基本类型、数组、对象、* 甚至是 Immutable.js 生成的数据结构。惟一的要点是* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。** 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。*/
    function counter(state = 0, action) {switch (action.type) {case 'INCREMENT':return state + 1;case 'DECREMENT':return state - 1;default:return state;}
    }// 创建 Redux store 来存放应用的状态。
    // API 是 { subscribe, dispatch, getState }。
    let store = createStore(counter);// 可以手动订阅更新,也可以事件绑定到视图层。
    store.subscribe(() =>console.log(store.getState())
    );// 改变内部 state 惟一方法是 dispatch 一个 action。
    // action 可以被序列化,用日记记录和储存下来,后期还可以以回放的方式执行
    store.dispatch({ type: 'INCREMENT' });// 1
    store.dispatch({ type: 'INCREMENT' });// 2
    store.dispatch({ type: 'DECREMENT' });// 1
    
  • 效果如下:
    在这里插入图片描述

3. redux入门例子——优化1(reducer 和 store拆开)

3.1 想要实现的效果

  • 因为上面的简单例子中的state没有在页面上渲染,所以简单优化一下,实现页面渲染操作,想呈现的效果如下:
    在这里插入图片描述

  • 如果用纯react写的话,很简单,代码如下:

    import { useState } from "react";function CountNum(){const [count,setCount] = useState(0);function add(){setCount(count => count+1);}function subtract(){setCount(count => count-1);}return(<div>当前数字是:{count}<br /><br /><button onClick={add}>点我 +1</button> <br /><br /><button onClick={subtract}>点我 -1</button></div>)
    }
    export default CountNum;
    
  • 但我们目的是用redux实现,所以继续……

3.2 代码设计

  • 项目结构,如下:
    在这里插入图片描述
  • store.js 和 countReducer.js 如下:
    在这里插入图片描述
  • CountNumRedux.jsx 组件如下:
    在这里插入图片描述
  • 看效果,有问题
    在这里插入图片描述
    怎么重新渲染?继续……

3.3 添加 重新渲染

  • 使用 useEffect 进行重新渲染,核心代码如下:

    useEffect(()=>{store.subscribe(()=>{console.log('订阅更新,打印2-----',store.getState());setCount(store.getState());});
    });
    

    在这里插入图片描述

  • 然后再看效果:
    在这里插入图片描述

  • 关于useEffect ,可以看下面的文章:
    React中组件通信02——消息订阅与发布、取消订阅以及卸载组件时取消订阅.

3.4 附代码

  • countReducer.js

    /*** 这是一个 reducer,形式为 (state, action) => state 的纯函数。* 描述了 action 如何把 state 转变成下一个 state。** state 的形式取决于你,可以是基本类型、数组、对象、* 甚至是 Immutable.js 生成的数据结构。惟一的要点是* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。** 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。*/function countReducer(state = 0,action){console.log(`state:${state}---action:${action}---type:${action.type}`);switch (action.type){case 'INCREMENT':return state + 1;case 'DECREMENT':return state - 1;default:return state;}
    }
    export default countReducer;
    
  • store.js

    import { createStore } from 'redux';import countReducer from './countReducer.js'const store = createStore(countReducer);export default store;
    
  • CountNumRedux.jsx

    import { useState,useEffect } from "react";
    import store from '../redux/store'function CountNumRedux(){const [count,setCount] = useState(0);function add(){// setCount(count => count+1);//派发action 改变内部 state 惟一方法是 dispatch 一个 action。store.dispatch({ type: 'INCREMENT' });}function subtract(){// setCount(count => count-1);store.dispatch({ type: 'DECREMENT' });}// 可以手动订阅更新,也可以事件绑定到视图层。// store.subscribe(() =>//     console.log('订阅更新,打印1-----',store.getState())// );useEffect(()=>{store.subscribe(()=>{console.log('订阅更新,打印2-----',store.getState());setCount(store.getState());});});return(<div>当前数字是:{count}    &nbsp;&nbsp;&nbsp;&nbsp;当前数字是:{store.getState()}  <br /><br /><button onClick={add}>点我 +1</button> <br /><br /><button onClick={subtract}>点我 -1</button></div>)
    }export default CountNumRedux;
    

4. redux入门例子——优化2(拆出action)

4.1 关于action的其他说明

  • 看官网怎么说:
    • Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action
    • 除了 type 字段外,action 对象的结构完全由你自己决定。比如下面的:
      	{type: ADD_TODO,text: 'Build my first Redux app'}{type: TOGGLE_TODO,index: 5}
      
      更多参考可看:https://github.com/redux-utilities/flux-standard-action.
    • 在 Redux 中的 action 创建函数只是简单的返回一个 action。如下:
      在这里插入图片描述

4.2 优化——拆出action

  • 根据官网上说的,做个简单优化,改动点如下:
    在这里插入图片描述
    效果就不展示了,因为这个还能继续优化,如下……

4.3 优化——动态加减数字

4.3.1 优化看效果

  • 如下:
    在这里插入图片描述
    在这里插入图片描述
  • 效果如下:
    在这里插入图片描述

4.3.2 附代码

  • 代码在上面基础上做了简单的调整,action的type抽出了变量,直接给代码了,如下:

  • countConst.js

    //定义常量export const INCREMENT = 'INCREMENT'; //加
    export const DECREMENT = 'DECREMENT'; //减
    
  • countAction.js

    // //加的时候
    // function incrementNum(){
    //     return { type: 'INCREMENT' };
    // }// //减的时候
    // function decrementNum(){
    //     return { type: 'DECREMENT' };
    // }import {INCREMENT,DECREMENT} from './countConst.js'//加的时候
    function incrementNum(number){return { type: INCREMENT,number:number };
    }//减的时候
    function decrementNum(number){return { type: DECREMENT,number:number };
    }export default{incrementNum,decrementNum}
    
  • CountNumRedux.jsx

    import { useState,useEffect,useRef, createRef } from "react";
    import store from '../redux/store'
    import countAction from '../redux/countAction'function CountNumRedux(){const [count,setCount] = useState(0);const numberRef = createRef();function add(){// setCount(count => count+1);//派发action 改变内部 state 惟一方法是 dispatch 一个 action。// store.dispatch({ type: 'INCREMENT' });// store.dispatch(countAction.incrementNum());// console.log(numberRef.current.value);let number = numberRef.current.value;// console.log(typeof number);  //stringstore.dispatch(countAction.incrementNum(parseInt(number)));}function subtract(){let number = parseInt(numberRef.current.value);store.dispatch(countAction.decrementNum(number));}useEffect(()=>{store.subscribe(()=>{console.log('订阅更新,打印2-----',store.getState());setCount(store.getState());});});return(<div>当前数字是:{count}    &nbsp;&nbsp;&nbsp;&nbsp;当前数字是:{store.getState()}  <br />浮动数字:<input type="number" ref={numberRef}/><br /><br /><button onClick={add}>点我 加数</button> <br /><br /><button onClick={subtract}>点我 减数</button></div>)
    }export default CountNumRedux;
    
  • countReducer.js

    import {INCREMENT,DECREMENT} from './countConst.js'function countReducer(state = 0,action){console.log(`state:${state}---action:${action}---type:${action.type}---number${action.number}`);switch (action.type){case INCREMENT:// return state + 1;return state + action.number;case DECREMENT:// return state - 1;return state - action.number;default:return state;}
    }
    export default countReducer;
    

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

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

相关文章

电子电子架构——AUTOSAR信息安全机制有哪些(下)

电子电子架构——AUTOSAR信息安全机制有哪些&#xff08;下&#xff09; 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 人们会在生活中不断攻击你。他们的主要…

Jenkins自动化部署前后端分离项目 (svn + Springboot + Vue + maven)有图详解

1. 准备工作 本文的前后端分离项目&#xff0c;技术框架是&#xff1a; Springboot Vue Maven SVN Redis Mysql Nginx JDK 所以首先需要安装以下&#xff1a; 在腾讯云服务器OpenCLoudOS系统中安装jdk&#xff08;有图详解&#xff09; 在腾讯云服务器OpenCLoudOS系统…

SVN的基本使用

一、SVN介绍 SVN&#xff08;Subversion&#xff09;是一个开源的版本控制系统&#xff0c;它专门用于管理文件和目录的变更。SVN 提供了一种集中式的版本控制方案&#xff0c;其中有一个中央仓库存储所有文件的历史记录和变更。 SVN使用方式相对简单&#xff0c;可以通过命令…

Python中TensorFlow的长短期记忆神经网络(LSTM)、指数移动平均法预测股票市场和可视化...

原文链接&#xff1a;http://tecdat.cn/?p23689 本文探索Python中的长短期记忆&#xff08;LSTM&#xff09;网络&#xff0c;以及如何使用它们来进行股市预测&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 相关视频 在本文中&#xff0c;你将看到如何使用…

DAZ To UMA⭐二.设置DAZ导出的形态键 和 Daz贴图位置

文章目录 🟧 形态键介绍及在Unity3D中的用途1️⃣ Daz中的形态键2️⃣ Blender 中的形态键3️⃣ 形态键在Unity中的作用🟩 设置DAZ导出的形态键1️⃣ 找到要导出的形态键名称2️⃣ 打开导出面板3️⃣ 设置导出规则举例 : 导出身体Morphs举例:导出嘴部Morphs🟦 获取模型纹…

浅析工具dirpro v1.2源码

文章目录 前言源码分析dirpro.pystart.pybackup.pyrely.pyresults.pyend.py 前言 工具简介 dirpro 是一款由 python 编写的目录扫描器专业版&#xff0c;操作简单&#xff0c;功能强大&#xff0c;高度自动化 自动根据返回状态码和返回长度&#xff0c;对扫描结果进行二次整理…

VLAN聚合简介

定义 VLAN聚合&#xff08;VLAN Aggregation&#xff0c;也称Super VLAN&#xff09;指在一个物理网络内&#xff0c;用多个VLAN&#xff08;称为Sub-VLAN&#xff09;隔离广播域&#xff0c;并将这些Sub-VLAN聚合成一个逻辑的VLAN&#xff08;称为Super-VLAN&#xff09;&…

【linux进程(一)】深入理解进程概念--什么是进程?PCB的底层是什么?

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux进程 1. 前言2. PCB初认…

一文读懂Llama 2(从原理到实战)

简介 Llama 2&#xff0c;是Meta AI正式发布的最新一代开源大模型。 Llama 2训练所用的token翻了一倍至2万亿&#xff0c;同时对于使用大模型最重要的上下文长度限制&#xff0c;Llama 2也翻了一倍。Llama 2包含了70亿、130亿和700亿参数的模型。Meta宣布将与微软Azure进行合…

iOS16新特性:实时活动-在锁屏界面实时更新APP消息 | 京东云技术团队

简介 之前在 《iOS16新特性:灵动岛适配开发与到家业务场景结合的探索实践》 里介绍了iOS16新的特性&#xff1a;实时更新&#xff08;Live Activity&#xff09;中灵动岛的适配流程&#xff0c;但其实除了灵动岛的展示样式&#xff0c;Live Activity还有一种非常实用的应用场景…

【Vue2.0源码学习】生命周期篇-模板编译阶段(template)

文章目录 1. 前言2. 模板编译阶段分析2.1 两种$mount方法对比2.2 完整版的vm.$mount方法分析 3. 总结 1. 前言 前几篇文章中我们介绍了生命周期的初始化阶段&#xff0c;我们知道&#xff0c;在初始化阶段各项工作做完之后调用了vm.$mount方法&#xff0c;该方法的调用标志着初…

【跟小嘉学习区块链】二、Hyperledger Fabric 架构详解

系列文章目录 【跟小嘉学习区块链】一、区块链基础知识与关键技术解析 【跟小嘉学习区块链】一、区块链基础知识与关键技术解析 文章目录 系列文章目录[TOC](文章目录) 前言一、Hyperledger 社区1.1、Hyperledger(面向企业的分布式账本)1.2、Hyperledger社区组织结构 二、Hype…

UML六大关系总结

UML六大关系有&#xff1a;继承、关系、聚合、组合、实现、依赖。分为通过图和代码总结这些关系。 1、继承 继承&#xff08;Inheritance&#xff09;&#xff1a;表示类之间的继承关系&#xff0c;子类继承父类的属性和方法&#xff0c;并可以添加自己的扩展。 继承&#x…

【Spring Boot】Spring Boot源码解读与原理剖析

这里写目录标题 前言精进Spring Boot首选读物“小册”变“大书”&#xff0c;彻底弄懂Spring Boot全方位配套资源&#xff0c;学不会来找我&#xff01;技术新赛道&#xff0c;2023领先抢跑 前言 承载着作者的厚望&#xff0c;掘金爆火小册同名读物《Spring Boot源码解读与原理…

Windows11 手把手教授开放端口

首先在控制面板点击“系统与安全”&#xff0c;找到防火墙 然后点击“windows defender”打开防火墙 点击左侧目录栏中“高级设置” 点击“入站规则”&#xff0c;再点击新建入站规则&#xff08;开放端口有开放入站端口与开放出站端口之分&#xff0c;这里讲入站端口的开放…

老胡的周刊(第109期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 lobe-chat[2] LobeChat 是一个开源的、可扩展…

Redis 缓存雪崩、缓存穿透、缓存击穿

Redis 是一种常用的内存缓存工具&#xff0c;但在某些情况下&#xff0c;它可能会遭受缓存雪崩、缓存穿透和缓存击穿等问题。下面是一些预防这些问题的建议&#xff1a; 1、缓存雪崩 缓存雪崩指的是在某个时间点上&#xff0c;大量的缓存数据同时失效或过期&#xff0c;导致大…

华为云云耀云服务器L实例评测|华为云上安装kafka

文章目录 华为云云耀云服务器L实例评测&#xff5c;华为云上安装kafka一、kafka介绍二、华为云主机准备三、kafka安装1. 安装什么版本java2. 安装zookeeper服务3. 使用systemctl 管理启动ZooKeeper服务4. 修改kafka配置5. 使用systemctl 管理启动kafka服务6. 创建一个测试 topi…

前端JavaScript中的 == 和 ===区别,以及他们的应用场景,快来看看吧,积累一点知识。

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 一、等于操作符 二、全等操作符 三、区别 小结 一、等于操作符 等于操作符用两个等于号&#xff08; &am…