redux react-redux @reduxjs/toolkit

news2025/1/5 15:20:47

redux团队先后推出了redux、react-redux、@reduxjs/toolkit,这三个库的api各有不同。本篇文章就来梳理一下当我们需要在项目中集成redux,从直接使用redux,到使用react-redux,再到react-redux和@reduxjs/toolkit配合使用,分别需要调用到哪些api。

一、在react中集成redux

redux中通过createStore可以创建出store实例,在该实例上存在三个实例方法。

通过store.subscribe可以监听到state的改变,引起组件的重新渲染。

通过dispatch可以分发action,引起redux内部state的更新。

通过getState可以获取到redux内部的state。

以一个简单的计数器程序作为示例。

首先在App组件中引入Count组件,为其传入store实例作为props。

import React from "react";
import Count from "./components/Count";
import store from "./store";

export default function App() {
  return <Count store={store} />;
}

在Count组件中,我们在组件挂载后通过store.subscribe监听redux的state,通过store,getState获取state,为按钮绑定点击事件,回调调用dispatch,传入action的返回值作为参数。

import React, { useEffect, useState } from "react";
import store from "../store";
import { createAddActions } from "../store/actions/count";

export default function Count() {
  const [_, rerender] = useState({});
  useEffect(() => {
    store.subscribe(() => rerender({}));
  }, []);
  return (
    <div>
      <div>sum: {store.getState()}</div>
      <button onClick={() => store.dispatch(createAddActions(1))}>
        点我+1
      </button>
    </div>
  );
}

接下来是store的编写。

// store/index.js

import { countReducer } from "./reducers/count";
import { createStore } from "redux";

export default createStore(countReducer);

reducers必须是一个纯函数,纯函数的概念是需要返回一个新的state替换原来的state,而不是直接在原来的state上修改。

// store/reducers/count.js

export function countReducer(prevState, action) {
  switch (action.type) {
    case "add":
      return prevState + action.value;
    default:
      return 0;
  };
};

action的实现。

// store/actions/count.js

export function createAddActions(value) {
  return {
    type: "add",
    value,
  };
};

二、在react中集成react-redux

react-redux提出了容器组件的概念,要求redux只能和容器组件进行通信,至于ui组件,只能通过props来获取容器组件传入的state和引起redux内部state改变的callback。

引入容器组件的目的在于尽量让ui组件内部看起来与其他不需要使用redux的组件无异。

如何理解无异呢?就是不要直接去调用store的实例方法,而是调用父组件提供的方法。当我们调用父组件提供的方法,而react-redux会再调用store的实例方法。

store.getState() -> props.state

store.dispatch() -> props.callback()

store.subscribe不再手动调用,而是由react-redux执行。

Count.js修改如下。

import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { createAddActions } from "../store/actions/count";

function Count(props) {
  return (
    <div>
      <div>sum: {props.state}</div>
      <button onClick={() => props.add(1)}>点我+1</button>
    </div>
  );
}

export default connect(
  (state) => ({ state }),
  (dispatch) => ({
    add: (number) => dispatch(createAddActions(number)),
  })
)(Count);

connect的第二个参数还可以简写为对象形式。

export default connect((state) => ({ state }), { add: createAddActions })(Count);

我们使用redux的目的是在多个组件之间共享state,所以我们直接引用redux时,需要在多个组件中传入store作为props,react-redux针对此也做了优化。

我们只需引入Provider包裹App组件,在Provider中传入store作为props,我们就可以在容器组件中获取到props。其实底层就是调用了react的SomeContext.Provider,内部组件只要使用useContext就可以获取到store。

// index.js

import React from "react";
import ReactDOM from 'react-dom/client';
import { Provider } from "react-redux";
import store from "./store";
import App from './App';

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

在Count组件中,我们不再需要手动传入store。

import React from "react";
import Count from "./components/Count";

export default function App() {
  return <Count />;
}

在现在的react-redux中,更推荐使用useSelector和useDispatch来代替connect。当我们使用useSelector和useDispatch获取state和分发action时,不再存在container组件,取而代之的是selector hook和dispatch hook。

对于connect而言,会优先从props中获取store,不存在的情况下再用React.useContext获取props,所以store有两种传入方式。

对于useSelector和useDispatch而言,他们只是Hook而不是组件,没有props,只能从React.useContext中获取store,所以如果外层没有Provider组件的话,项目是无法运行的。

此外,connect和Provider都实现了对store的监听。

import React, { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { createAddActions } from "../store/actions/count";

export default function Count() {
  const state = useSelector((state) => state);
  const dispatch = useDispatch();
  return (
    <div>
      <div>sum: {state}</div>
      <button onClick={() => dispatch(createAddActions(1))}>点我+1</button>
    </div>
  );
}

三、在React中集成@reduxjs/toolkit和react-redux

@reduxjs/toolkit的作用如下:

1. 将initialState、reducers、actions整合在一起形成切片

2. 自动生成action,{name: sliceName/reducerName, payload: value}

3. 代替redux/thunk实现异步action功能

// store/slices/count.js

import { createSlice } from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    add: (state, action) => {
      return state + action.payload;
    },
  },
});

export const { add } = counterSlice.actions;

export default counterSlice.reducer;
// store/index.js

import countReducer from "./slices/count";
import { configureStore } from "@reduxjs/toolkit";

export default configureStore({
  reducer: countReducer // reducer的结构对应state的结构
});

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

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

相关文章

Visual Studio 2022安装教程

1、下载网址 Visual Studio 2022 IDE安装网址借助 Visual Studio 设计&#xff0c;具有自动完成、构建、调试、测试功能的代码将与 Git 管理和云部署融为一体。https://visualstudio.microsoft.com/zh-hans/vs/ 点击图片所示 双击运行 2、安装 点击C桌面开发&#xff08;右边…

Mono里运行C#脚本21—mono_image_init_name_cache

前面分析了怎么样加载mscorlib.dll文件,然后把文件数据读取到内存。 接着下来,就会遇到加载整个C#的类型系统,比如System. Object,大体类型如下图所示: 在对CIL编译之前,需要把这些类型全部加载到内存里,以便快捷地访问它们。 mono_image_init_name_cache函数就是完成…

C/C++编程安全标准GJB-8114解读——分支控制类

软件测试实验室在建立软件测试体系或申请cnas/cma相关资质时&#xff0c;需要依据相关技术标准选择合适的测试方法&#xff0c;并明确在测试作业指导书中&#xff0c;指导后续软件测试工作的开展。GJB-8114是一部嵌入式软件安全测试相关的国家标准&#xff0c;本系列文章我们就…

国产文本编辑器EverEdit - 批量转码转换行符

1 批量转码&转换行符 1.1 应用场景 如果用户批量在Windows编辑文件&#xff0c;要上传到异构系统&#xff0c;如&#xff1a;Linux&#xff0c;则需要批量转换编码和换行符&#xff0c;此时可以使用EverEdit的批量转码功能。 1.2 使用方法 选择主菜单文档 -> 批量转码…

期权懂|期权都有哪些存在的风险因素?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 期权都有哪些存在的风险因素&#xff1f; 一、市场价格波动风险 期权的价格受到多种因素的影响&#xff0c;包括标的资产价格、市场利率、波动率等。 这些因素的变化可能导致期…

关于AI面试系统2025年趋势评估!

在快速发展的科技浪潮中&#xff0c;AI技术正以前所未有的速度渗透到各行各业。企业招聘领域&#xff0c;作为人才选拔的关键环节&#xff0c;也不例外地迎来了AI面试系统的广泛应用和持续创新。2025年&#xff0c;AI面试系统不仅成为企业招聘的主流工具&#xff0c;更在智能化…

《类和对象:基础原理全解析(下篇)》

目录 一、类的构造函数的初始化列表1. 初始化列表的使用2. 初始化列表的初始化顺序3. 使用初始化列表的注意事项 二、类的自动类型转换1. 类的自动类型转换的使用2. 关闭类的自动类型转换 三、静态类成员1. 静态成员的特性2. 使用静态成员计算类创建了多少个对象3. 使用静态类成…

分析服务器 systemctl 启动gozero项目报错的解决方案

### 分析 systemctl start beisen.service 报错 在 Linux 系统中&#xff0c;systemctl 是管理系统和服务的主要工具。当我们尝试重启某个服务时&#xff0c;如果服务启动失败&#xff0c;systemctl 会输出错误信息&#xff0c;帮助我们诊断和解决问题。 本文将通过一个实际的…

Crosslink-NX应用连载(12):如何复用特殊功能管脚

作者&#xff1a;Hello,Panda 大家早上好。 昨天有朋友私信我&#xff0c;如何复用Crosslink-NX的特殊功能引脚如PROGRAMN、DONE、INITN诸如这些。熊猫君在这里简单介绍下&#xff1a; 以LIFCL-33U-8CTG104C为例&#xff0c;我们建立一个简单的指示灯LED周期闪烁的工程&…

go项目使用gentool生成model的gen.go问题

Gen Tool 是一个没有依赖关系的二进制文件&#xff0c;可以用来从数据库生成结构。 使用方法&#xff1a; go install gorm.io/gen/tools/gentoollatest在项目根目录,执行连接的数据库中指定某几张表结构生成数据库model层 gentool -dsn "root:123456tcp(localhost:330…

家政上门小程序如何创建?家政服务怎么能少了小程序帮手

在如今这个“忙到没时间打扫”的时代&#xff0c;家政服务变得越来越受欢迎。为了提高效率、减少沟通成本&#xff0c;很多家政公司都已经开始借助小程序的力量。那么&#xff0c;家政上门小程序到底该如何创建呢?小程序又是如何帮助家政服务更好地满足客户需求的呢?本文将为…

破解密码

rhel8/centos8 重置 root 密码 方法 1 &#xff1a; rd.break 第 1 步 重启系统&#xff0c;在下图所示界面按 e 键 第2步 找到linux这行&#xff0c;末尾空格后 输入 rd.break 第3步 查看&#xff0c;可选步骤 这里 sysroot 是以只读的形式挂载的&#xff0c;所以要以可读可…

本地小主机安装HomeAssistant开源智能家居平台打造个人AI管家

文章目录 前言1. 添加镜像源2. 部署HomeAssistant3. HA系统初始化配置4. HA系统添加智能设备4.1 添加已发现的设备4.2 添加HACS插件安装设备 5. 安装cpolar内网穿透5.1 配置HA公网地址 6. 配置固定公网地址 前言 大家好&#xff01;今天我要向大家展示如何将一台迷你的香橙派Z…

自学记录鸿蒙API 13:实现多目标识别Object Detection

起步&#xff1a;什么叫多目标识别&#xff1f; 无论是生活中的动物识别、智能相册中的场景分类&#xff0c;还是工业领域的检测任务&#xff0c;都能看到多目标识别的身影。这次&#xff0c;我决定通过学习HarmonyOS最新的Object Detection API&#xff08;API 13&#xff09…

javaEE-多线程进阶-JUC的常见类

juc:指的是java.util.concurrent包&#xff0c;该包中加载了一些有关的多线程有关的类。 目录 一、Callable接口 FutureTask类 参考代码&#xff1a; 二、ReentrantLock 可重入锁 ReentrantLock和synchronized的区别&#xff1a; 1.ReentantLock还有一个方法&#xff1a…

fpga系列 HDL:ModelSim显示模拟波形+十进制格式数值(临时方法和设置持久化的默认值)

模拟波形 FPGA中使用数字滤波器时&#xff0c;可通过观察模拟波形更好地查看滤波效果。可以通过ModelSim中的波形格式设置来实现更直观的波形显示。右键波形->Format-> Analog 效果 数值格式显示 不同的数值格式显示&#xff1a;右键波形->Radix-> Decimal 效果…

Linux 中 sysctl 和 systemctl 有什么区别?

sysctl 和 systemctl 是两个不同的命令行工具&#xff0c;它们在 Linux 系统中分别用于不同的目的。理解这两个命令的区别对于系统管理和配置非常重要。 1. sysctl 功能 用途&#xff1a;sysctl 用于动态地修改内核参数&#xff0c;这些参数控制着操作系统的某些行为。配置文…

【ArcGISPro/GeoScenePro】检查并处理高程数据

数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 数字高程模型 (DEM) 是一种栅格,可显示地面或地形的高程。 数字表面模型 (DSM) 是另一种高程栅格,可显示表面的高度,例如建筑物或树冠的顶部。 您需要准备 DEM 和 DSM 以供分析…

Redis数据库主要数据结构类型

Redis数据库提供了丰富多样的数据结构类型&#xff0c;以满足不同场景下的数据存储需求。以下是Redis中的主要数据结构类型&#xff1a; 一、五种基础数据结构 字符串&#xff08;String&#xff09; 简介&#xff1a;字符串是Redis最基本的数据类型&#xff0c;可以存储字符串…

基于Springboot + vue实现的校园周边美食探索及分享平台

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…