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

news/2024/7/15 19:01:51 标签: react.js, 前端, 前端框架, 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入门例子——优化(reducer 和 store拆开)
    • 3.1 想要实现的效果
    • 3.2 代码设计
    • 3.3 添加 重新渲染
    • 3.4 附代码

1. 前言

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

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

redux_6">1.2 介绍redux

1.2.1 参考官网

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

redux_10">1.2.2 redux原理图

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

redux_18">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 本身。

redux_38">1.3 安装redux

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

redux_43">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
    
  • 效果如下:
    在这里插入图片描述

reduxreducer__store_90">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 添加 重新渲染

  • 使用 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;
    

http://www.niftyadmin.cn/n/5038450.html

相关文章

Canal实现Mysql数据同步至Redis、Elasticsearch

文章目录 1.Canal简介1.1 MySQL主备复制原理1.2 canal工作原理 2.开启MySQL Binlog3.安装Canal3.1 下载Canal3.2 修改配置文件3.3 启动和关闭 4.SpringCloud集成Canal4.1 Canal数据结构![在这里插入图片描述](https://img-blog.csdnimg.cn/c64b40c2231a4ea39a95aac81d771bd1.pn…

玩转Mysql系列 - 第23篇:mysql索引管理详解

这是Mysql系列第23篇。 环境&#xff1a;mysql5.7.25&#xff0c;cmd命令中进行演示。 代码中被[]包含的表示可选&#xff0c;|符号分开的表示可选其一。 关于索引的&#xff0c;可以先看一下前2篇文章&#xff1a; 什么是索引&#xff1f; mysql索引原理详解 本文主要介…

flink集群与资源@k8s源码分析-资源II 资源提供

1 资源 资源分析分3部分,资源请求,资源提供,声明式资源管理,本文是第二部分资源提供 2 注册任务管理器/报告资源 任务管理器启动后注册到资源管理器,报告自身资源,资源通过这个方式新增的 1. 任务管理器启动,同时启动高可用组件,触发 ResourceManagerLeaderListener…

基于Android+OpenCV+CNN+Keras的智能手语数字实时翻译——深度学习算法应用(含Python、ipynb工程源码)+数据集(五)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 数据增强3. 模型构建4. 模型训练及保存5. 模型评估6. 模型测试 系统测试1. 训练准确率2. 测试效果3. 模型应用1&#xff09;程序下载运行2&#xff09;应用使用说明3&#xff09;测试结果 相关其它…

如何隐藏或修改Docker容器中的Nginx响应头中的Server

背景介绍 现在大部分项目通过Nginx作为反向代理&#xff0c;实际由于安全审计要求需要隐藏或修改响应头的Server信息&#xff0c;传统的项目直接部署在nginx服务器中&#xff0c;只需要在nginx服务器安装ngx_http_headers_more_filter_module插件&#xff0c;然后通过修改ngin…

安防监控系统/视频云存储/视频监控平台EasyCVR无法级联上级平台,该如何解决?

安防视频监控系统EasyCVR平台能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多路视频流&#xff0c;也…

ES6之Map和Set有什么不同?

一、Map 1.定义 Map是ES6提供的一种新的数据结构&#xff0c;它是键值对的集合&#xff0c;类似于对象&#xff0c;但是键的范围不限于字符串&#xff0c;各种类型的值都可以当做键。 Object结构是“字符串-值”的对应&#xff0c;Map结构则是“值-值”的对应 2.代码示例 M…

淘宝分布式文件存储系统( 二 ) -TFS

淘宝分布式文件存储系统( 二 ) ->>TFS 目录 : 大文件存储结构哈希链表的结构文件映射原理及对应的API文件映射头文件的定义 大文件存储结构 : 采用块(block)文件的形式对数据进行存储 , 分成索引块,主块 , 扩展块 。所有的小文件都是存放到主块中的 &#xff0c;扩展块…