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

2023-09-20 22:54:01

1. 前言

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

1.2 介绍redux

1.2.1 参考官网

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入门例子——优化(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 添加 重新渲染

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;
    
更多推荐

GaussDB数据库SQL系列-子查询

目录一、前言二、GaussDBSQL子查询表达式1、EXISTS/NOTEXISTS2、IN/NOTIN3、ANY/SOME4、ALL三、GaussDBSQL子查询实验示例1、创建实验表2、EXISTS/NOTEXISTS示例3、IN/NOTIN示例4、ANY/SOME示例5、ALL示例四、注意事项及建议五、小结一、前

新装机电脑网速特别慢

老主机最近有些问题,我一直没能解决,也用了5年了,索性出给闲鱼二道贩子,又自己新配置了一台主机。具体表现为:主机插网线后,跟之前主机比,浏览网页或者下载资源速度特别慢,打开百度浏览器都要转上一会,不管下载什么资源,下载速度最快只有100-200kb,让我梦回05年,重新体验了一把当年的感觉,实在抓狂。主板带有WIFI功

3D WEB引擎HOOPS Commuicator助力Naval Architect Jumpstart快速启动船舶信息建模平台开发

行业:造船业挑战:新公司希望将创新的船舶信息建模产品推向市场-基于浏览器的产品需要支持高级可视化和强大的数据转换,以处理大型、复杂的造船项目-小型开发团队的任务是雄心勃勃的平台发布计划。解决方案:TechSoft3D提供领先的SDK,可加速强大的工程Web应用程序的开发。结果:利用第三方组件进行3DWeb轻量化、数据转

负载均衡中间件---Nginx

一.nginx的好处学习Nginx对于一个全栈开发者来说是非常有价值的,下面是一些学习Nginx的原因和好处:反向代理和负载均衡:Nginx是一个高性能的反向代理服务器,可以用于将客户端请求转发给多个后端服务器,实现负载均衡。学习Nginx可以让您了解如何配置和管理反向代理和负载均衡,以提高应用程序的性能和可靠性。静态

layui框架学习(45: 工具集模块)

layui的工具集模块util支持固定条、倒计时等组件,同时提供辅助函数处理时间数据、字符转义、批量事件处理等操作。util模块中的fixbar函数支持设置固定条(2.7版本的帮助文档中叫固定块),是指固定在页面一侧的工具条元素,不随页面滚动条滚动,默认在页面右下角位置。fixbar函数的原型为util.fixbar(

Docker vs. Podman: 选择容器技术的智慧之选

嗨,各位亲爱的程序员小伙伴们!当我们步入容器技术的世界,往往会在众多选择中迷茫。两个备受瞩目的容器工具,Docker和Podman,都在业界掀起了一股风潮。今天,我将带你深入探索,为什么在Docker和Podman之间做出选择,以及如何根据自身需求来做出明智的决策。就让我们一同踏上这个容器之旅吧!容器技术简介:为何容器

初识Docker

文章目录Docker安装Docker简介1.什么是虚拟化、容器化?2.为什么需要虚拟化、容器化?3.虚拟化的实现方式主机虚拟化的实现方式容器虚拟化实现4.虚拟机和Docker的区别Docker安装基于Centos7进行安装1.确认系统版本和CPU架构,Centos7的x86_64架构#cat/etc/*release*

大数据之Hive(三)

分区表概念和常用操作将一个大表的数据按照业务需要分散存储到多个目录,每个目录称为该表的一个分区。一般来说是按照日期来作为分区的标准。在查询时可以通过where子句来选择查询所需要的分区,这样查询效率会提高很多。①创建分区表hive(default)>createtabledept_partition(deptnoint

MySQL学习系列(4)-每天学习10个知识

目录1.InnoDB和MyISAM2.SQL调优3.数据一致性问题的解决4.MySQL的存储引擎5.MySQL的内存使用问题6.索引比全表扫描慢的情况7.行级锁和表级锁8.MySQL的复制功能9.数据库性能测试10.数据库管理和优化👍点赞,你的认可是我创作的动力!⭐️收藏,你的青睐是我努力的方向!✏️评论,你的意见是

2023年的深度学习入门指南(27) - CUDA的汇编语言PTX与SASS

通过前面的学习,我们了解了在深度学习和大模型中,GPU的广泛应用。可以说,不用说没有GPU,就算是没有大显存和足够先进的架构,也没法开发大模型。有的同学表示GPU很神秘,不知道它是怎么工作的。其实,GPU的工作原理和CPU是一样的,都是通过指令来控制硬件的。只不过,GPU的指令集和CPU不一样。下面我们就走进GPU的内

2023/9/20 -- C++/QT

时钟:widget.h:#ifndefWIDGET_H#defineWIDGET_H#include<QWidget>#include<QPainter>#include<QPaintEvent>#include<QDateTime>#include<QLabel>#include<QTimer>#include<QD

热文推荐