Redux - Redux在React函数式组件中的基本使用

在这里插入图片描述

文章目录

    • 一,简介
    • 二,安装
    • 三,三大核心概念Store、Action、Reducer
      • 3.1 Store
      • 3.2 Reducer
      • 3.3 Action
    • 四,开始函数式组件中使用
      • 4.1,引入store
      • 4.1,store.getState()方法
      • 4.3,store.dispatch()方法
      • 4.4,store.subscribe()方法
    • 五,Redux 的三大原则

一,简介

Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。

它主要的几个方法如下:

在这里插入图片描述
重要的有方法 有 dispatch(分发action)getState(获取state)subscribe(监听state的变化),下面会介绍到,另外两个可以不用管;


那什么时候使用Redux呢?

当遇到如下问题时,建议开始使用 Redux

  1. 你有很多数据随时间而变化
  2. 你希望状态有一个唯一确定的来源(single source of truth)
  3. 你发现将所有状态放在顶层组件中管理已不可维护

二,安装

我这里安装的是 "redux": "^4.2.1"版本;

npm install redux --save

项目的src目录下面新建store文件夹index.js,reducer.js;如下:

在这里插入图片描述

三,三大核心概念Store、Action、Reducer

3.1 Store

Store:存储数据的地方。最好整个应用只有一个 Store。

createStore() :用来生成 Store。接收 Reducer 作为其参数。

index.js

/**
 * 引入createStore 专门创建最为核心的store对象
 * 目前createStore已经弃用,所以我们要引用legacy_createStore 
 */

iimport { legacy_createStore } from "redux";
import reducer from './reducer.ts'

// 创建数据仓库 引入reducer函数进行对数据的处理
const store = legacy_createStore(reducer)

export default store

3.2 Reducer

reduce的本质就是一个函数 ,作用是初始化状态和加工状态。

reduce函数里面接收两个参数,第一个参数是state的初始值,第二个参数是一个action对象,对象里的第一个属性是type也就是函数的名称,第二个属性就是传进来的值,用于后续更改state;

reducer.ts


// 约束类型
interface Eula {
  name: string;
  age: number;
}
// 定义数据
const defaultState: Eula = {
  name: "Eula",
  age: 18
};

// reducer 函数 用于更改数据
let reducer = (preState = defaultState, action: { type: string; data: number }) => {
  // action解构出来
  let { type, data } = action;

  // 第一种写法 每个分支使用return进行返回
  // switch (type) {
  //   case "update_age":
  //     preState.age = data;
  //     return preState;
  //   case "add_age":
  //     preState.age++;
  //     return preState;
  //   case "del_age":
  //     preState.age--;
  //     return preState;
  //   default:
  //     return preState; // 初始化时
  // }

  // 第二种写法 break 与最终的return返回结果
  switch (type) {
    case "update_age":
      preState.age = data;
      break;
    case "add_age":
      preState.age++;
      break;
    case "del_age":
      preState.age--;
      break;
    default:
      preState; // 初始化时
  }
  return preState;  // 此处 一定要使用return进行返回最终改变的值
};

export default reducer;

注意: 初次加载 Store 会自动调用一次 Reducer 进行初始化状态,此时 state 是 undefined,action 对象中的 type 为 @@redux/INITxxx。手动调用 store.dispatch() 也会触发 Reducer 的自动执行。

3.3 Action

Action 就是一个普通的 JS 对象,用于描述要更新的数据类型和内容,其中 type 属性是必须的,表示 Action 的名称,其他属性可以自由设置。

redux.tsx

// 引入store
import store from "../../../store/index";
// 更改数据时调用
store.dispatch({ type: "update_age", data: 100 });

store.dispatch():所有数据的变化,必须通过派发(dispatch) Action 来更新。接受一个 Action 对象作为参数,将其发送出去。

四,开始函数式组件中使用

redux.tsx

import React, { useState } from "react";
//  1,引入store
import store from "../../../store/index";

// 渲染数据
const myList:[] = [];

const Redux: React.FC = () => {
  let [list, setList] = useState(myList);
  console.log("store:", store);

  // 监听数据的变化
  const unsubscribe = store.subscribe(() => {
    console.log("订阅数据的变化", store.getState());
    // 此处用来触发视图的更新
    setList([]);
  });

  // 改变store中的数据
  const update = () => {
    store.dispatch({ type: "update_age", data: 100 });
  };
  const add = () => {
    store.dispatch({ type: "add_age" });
  };
  const del = () => {
    store.dispatch({ type: "del_age" });
  };

  // 此处才是真正渲染的页面
  return (
    <div className="redux">
      <h3>redux演示</h3>
      <button onClick={update}>更改store的数据+100</button>
      <button onClick={add}>更改store的数据++</button>
      <button onClick={del}>更改store的数据--</button>
      <p>store的num数据:{store.getState().age}</p>
    </div>
  );
};
export default Redux;

效果图:

在这里插入图片描述

上面的组件是一个简单的案例演示,定义了三个点击事件,点击第一个按钮state.age+100,点击第二个按钮每次state.age+1,点击第三个按钮age每次减一;下面会详细介绍几个重点内容:

4.1,引入store

先引进来,这个没什么好说的;

import store from "../../../store/index";

4.1,store.getState()方法

getState()方法是redux实例下的方法之一,上面的第一张截图已经通过store实例打印出来了;

getState()的作用是获取当前状态下运行在redux中的state;也就是说获取store中最新的数据;

   <p>store的num数据:{store.getState().age}</p>

4.3,store.dispatch()方法

dispatch() 是唯一能够修改 state 数据的行为。通过分发action (其实就是一个对象),配合 dispatch 函数传入的 action 及其 payload 计算得到新的 state,并更新到闭包数据中,这样就实现了 state 的更新;

如下:
reducer.tsx

  // 改变store中的数据
  const update = () => {
    store.dispatch({ type: "update_age", data: 100 });
  };
  const add = () => {
    store.dispatch({ type: "add_age" });
  };
  const del = () => {
    store.dispatch({ type: "del_age" });
  };

上面的代码会和下面的 switch case 表达式所判断的type要一 一对应,用于更新state;

reducer.ts

let reducer = (preState = defaultState, action: { type: string; data: number }) => {
  let { type, data } = action;
  
  // 第一种写法 每个分支使用return进行返回
  // switch (type) {
  //   case "update_age":
  //     preState.age = data;
  //     return preState;
  //   case "add_age":
  //     preState.age++;
  //     return preState;
  //   case "del_age":
  //     preState.age--;
  //     return preState;
  //   default:
  //     return preState; // 初始化时
  // }

  // 第二种写法 break 与最终的return返回结果
  switch (type) {
    case "update_age":
      preState.age = data;
      break;
    case "add_age":
      preState.age++;
      break;
    case "del_age":
      preState.age--;
      break;
    default:
      preState; // 初始化时
  }
  return preState;  // 此处 一定要使用return进行返回最终改变的值
};

上面的两种写法是一样的;对比一下;

4.4,store.subscribe()方法

subscribe函数只要store中的state数据变化了,就会触发subscribe方法,相当注册了一个监听器;监听store中的数据变化;

从 react 层面来说,redux 的 store 是隔离开的,我们需要一个桥梁,使得数据层出现更新的同时更新UI层逻辑,这时 store 中的最后一个方法,subscribe 方法就派上用场了。

注意: setList([]):是为了主动触发react视图更新的方法,否则store中数据改变了,视图却没有重新渲染。

import React, { useState } from "react";
const Redux: React.FC = () => { 
  let [list, setList] = useState(myList);
// 监听数据的变化
  const unsubscribe = store.subscribe(() => {
    console.log("订阅数据的变化", store.getState());
    // 此处用来触发视图的更新
    setList([]);
  });
}

subscribe也同时返回了一个 unsubscribe 函数。当我们不在希望订阅这个监听器时,调用 unsubscribe(),对应的函数就会从监听器队列中被移除。

unsubscrib() // 不再监听

五,Redux 的三大原则

  1. 单一数据源:整个应用程序的 State 被存储在一棵 object tree 中,并且这棵 object tree 只存储在一个 Store 中。单一数据源可以让整个应用程序的 State 变得方便维护、修改、追踪。
  2. State 是只读的:唯一修改 State 的方法就是触发 Action,不要试图在其他地方通过任何的方式来修改State。这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行。
  3. 使用纯函数来执行修改:通过 Reducer 将旧的 State 和 Action 联系在一起,返回一个新的 State。所有的Reducer 都应该是纯函数,不能产生任何的副作用。

End:


[redux中文网]: https://cn.redux.js.org/

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言入门 Day_5 四则运算

目录 前言 1.四则运算 2.其他运算 3.易错点 4.思维导图 前言 图为世界上第一台通用计算机ENIAC,于1946年2月14日在美国宾夕法尼亚大学诞生。发明人是美国人莫克利&#xff08;JohnW.Mauchly&#xff09;和艾克特&#xff08;J.PresperEckert&#xff09;。 计算机的最开始…

centos7安装erlang及rabbitMQ

下载前注意事项&#xff1a; 第一&#xff1a;自己的系统版本&#xff0c;centos中uname -a指令可以查看&#xff0c;el8&#xff0c;el7&#xff0c;rabbitMQ的包不一样&#xff01; 第二&#xff1a;根据rabbitMQ中erlang version找到想要下载rabbitMQ对应erlang版本&#x…

深度学习优化器

1、什么是优化器 优化器用来寻找模型的最优解。 2、常见优化器 2.1. 批量梯度下降法BGD(Batch Gradient Descent) 2.1.1、BGD表示 BGD 采用整个训练集的数据来计算 cost function 对参数的梯度&#xff1a; 假设要学习训练的模型参数为W&#xff0c;代价函数为J(W)&#xff0c;…

FOSSASIA Summit 2023 - 开源亚洲行

作者 Ted 致歉&#xff1a;本来这篇博客早就该发出&#xff0c;但是由于前几个月频繁差旅导致精神不佳&#xff0c;再加上后续我又参加了 Linux 基金会 7/27 在瑞士日内瓦举办的 Open Source Congress&#xff0c;以及 7/29-30 台北的 COSCUP23&#xff0c;干脆三篇连发&#x…

利用三维内容编辑器制作VR交互课件,简单好用易上手

随着虚拟现实技术的不断发展&#xff0c;越来越多的教育机构开始尝试将其应用于教育教学中。然而&#xff0c;要实现这一目标并不容易&#xff0c;需要专业的技术支持和开发团队。 为了解决这一问题&#xff0c;广州华锐互动研发了三维内容编辑器&#xff0c;它是一种基于虚拟现…

使用wxPython嵌入浏览器加载本地HTML文件

使用wxPython模块嵌入浏览器并加载本地HTML文件的示例博客。以下是一个简单的示例&#xff1a; 介绍&#xff1a; 在本篇博客中&#xff0c;我们将使用Python的wxPython模块来嵌入一个浏览器&#xff0c;并加载一个本地的HTML文件。这对于需要在Python应用程序中显示Web内容…

word之插入尾注+快速回到刚才编辑的地方

1-插入尾注 在编辑文档时&#xff0c;经常需要对一段话插入一段描述或者附件链接等&#xff0c;使用脚注经常因占用篇幅较大导致文档页面内容杂乱&#xff0c;这事可以使用快捷键 ControlaltD 即可在 整个行文的末尾插入尾注&#xff0c;这样文章整体干净整洁&#xff0c;需…

髋关节 弹响

评估测试 https://www.bilibili.com/video/BV1A44y1j71Y/?spm_id_from333.880.my_history.page.click&vd_source3535bfaa5db8443d107998d15e88dc44 根据此视频整理所得 托马斯测试 第一种情况 如果你难于将膝关节拉到胸前&#xff0c;并感觉前面有骨性的挤压 说明你股…

分析 Linux 启动流程基本实现

下载 Linux 内核网址&#xff1a; https://www.kernel.org/ 最新 Linux 内核是 5.15 版本。现在常用 Linux 内核源码为4.14、4.19、4.9 等版本&#xff0c;其中 4.14 版本源码压缩包大概 90M&#xff0c;解压后 700M&#xff0c;合计 61350 个文件。如此众多的文件&#xff0…

会一点stm32,只后是做嵌入式Linux还是转JAVA?

选择嵌入式Linux还是转向JAVA&#xff0c;取决于你的兴趣、职业规划和就业市场的需求。以下是一些考虑因素&#xff1a;兴趣和擅长&#xff1a;首先&#xff0c;你应该考虑自己对嵌入式Linux和JAVA的兴趣和擅长程度。如果你对嵌入式系统、硬件交互和底层编程更感兴趣&#xff0…

如何在iPhone手机上修改手机定位和模拟导航?

如何在iPhone手机上修改手机定位和模拟导航&#xff1f; English Location Simulator&#xff08;定位模拟工具&#xff09; 是一款功能强大的 macOS 应用&#xff0c;专为 iPhone 用户设计&#xff0c;旨在修改手机定位并提供逼真的模拟导航体验。无论是为了保护隐私、测试位…

uniapp文件下载并预览

大概就是这样的咯&#xff0c;文件展示到页面上&#xff0c;点击文件下载并预览该文件&#xff1b; 通过点击事件handleDownLoad(file.path)&#xff0c;file.path为文件的地址&#xff1b; <view class"files"><view class"cont" v-for"(…

MongoDB 分片集群

在了解分片集群之前&#xff0c;务必要先了解复制集技术&#xff01; 1.1 MongoDB复制集简介 一组Mongodb复制集&#xff0c;就是一组mongod进程&#xff0c;这些进程维护同一个数据集合。复制集提供了数据冗余和高等级的可靠性&#xff0c;这是生产部署的基础。 1.1.1 复制集…

pip install mysql出现error: subprocess - exited-with-error的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

交叉编译基本概念

1 什么是交叉编译 1.1 本地编译 在解释什么是交叉编译之前&#xff0c;要先明白什么是本地编译。 本地编译可以理解为&#xff0c;在当前编译平台下&#xff0c;编译出来的程序只能放到当前的平台下运行&#xff0c;平时我们常见的软件开发都是属于本地编译。 比如我们在X8…

利用OpenCV光流算法实现视频特征点跟踪

光流简介 光流&#xff08;optical flow&#xff09;是运动物体在观察成像平面上的像素运动的瞬时速度。光流法是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系&#xff0c;从而计算出相邻帧之间物体的运动信息的一种方法。…

突破防线!泛微OA任意文件上传Getshell

子曰&#xff1a;“巧言令色&#xff0c;鲜矣仁。” 漏洞复现 访问漏洞url&#xff1a; 存在漏洞的路径为 /weaver/weaver.common.Ctrl/.css?arg0com.cloudstore.api.service.Service_CheckApp&arg1validateApp漏洞利用&#xff1a; 漏洞证明&#xff1a; 文笔生疏&…

win11如何去掉桌面快捷方式的小箭头(原创)

begin 打开注册表,Windows搜索框里搜 注册表编辑器(register editor),打开.. 找到 接着跟进.. 新建一个项名, Shell Icons 继续.... 值设为29 双击开页面 输入数据 %windir%\System32\shell32.dll,-51 到此,保存,到桌面,小箭头还是没有消失 ctrl shift esc 打开 任务管理…

Java课题笔记~ 数据提交的方式

前四种数据注入的方式&#xff0c;会自动进行类型转换。但无法自动转换日期类型。 &#xff08;1&#xff09;单个数据&#xff08;基本数据类型&#xff09;注入 在方法中声明一个和表单提交的参数名称相同的参数&#xff0c;由框架按照名称直接注入。 &#xff08;2&#x…

Kafka API与SpringBoot调用

文章目录 首先需要命令行创建一个名为cities的主题&#xff0c;并且创建该主题的订阅者。 1、使用Kafka原生API1.1、创建spring工程1.2、创建发布者1.3、对生产者的优化1.4、批量发送消息1.5、创建消费者组1.6 消费者同步手动提交1.7、消费者异步手动提交1.8、消费者同异步手动…