当前位置: 首页 > news >正文

【react】Redux基础用法

1. Redux基础用法

Redux 是一个用于 JavaScript 应用的状态管理库,它不依赖于任何 UI库,但常用于与 React 框架配合使用。它提供了一种集中式的状态管理方式,将应用的所有状态保存在一个单一的全局 Store(存储)中,使得状态的变化和共享变得更加可控和可预测。

Redux 的核心概念:

  • Store
    Redux 的 Store 是一个对象,存储了应用的全部状态。应用中只有一个 Store,作为单一数据源。任何组件需要访问状态时都会从这个 Store 中获取数据。

  • Action
    Action 是一个简单的 JavaScript 对象,用**来描述要执行的状态变化。**它通常包含两个部分:type(字符串,描述 Action 的类型)和 payload(可选,用来传递需要修改的数据信息)。Action 是 Redux 中唯一触发状态更新的方式。

  • Reducer
    Reducer 是一个纯函数,定义了应用在接收到不同 Action 时如何更新状态。它接收当前的状态和 Action,返回一个新的状态对象。

  • Dispatch
    Dispatch 是 Redux 中触发 Action 的方法。调用 store.dispatch(action) 可以将 Action 发送到 Store,从而触发 Reducer 更新状态。

  • Selectors
    Selectors 是从 Store 中获取特定状态的函数,主要用于简化和集中获取逻辑,避免直接访问 Store 造成的代码冗余。

  • Middleware
    Redux 中间件是在 dispatch 和 reducer 之间的一个逻辑层,可以用于处理异步操作(如 redux-thunk)或记录状态变化(如 redux-logger)。中间件增强了 Redux,使其能够处理复杂的逻辑和副作用。

简单计数器案例:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/redux/4.2.0/redux.min.js"></script><body><button id="increment">+</button><span id="count">0</span><button id="decrement">-</button>
</body><script>// 1.定义reducer函数// 作用:根据不同的action对象,返回不同的新的state// state:管理的数据初始状态// action:对象 type 标记当前想要做什么样的修改function reducer(state = { count: 0 }, action) {// 数据不可变:基于原始状态生成一个新的状态if (action.type === 'INCREMENT') {return { count: state.count + 1 }}if (action.type === 'DECREMENT') {return { count: state.count - 1 }}return state}// 2. 使用reducer函数创建store对象const store = Redux.createStore(reducer)// 3. 通过store对象的dispatch,修改store中的数据const inBtn = document.getElementById('increment')const deBtn = document.getElementById('decrement')inBtn.addEventListener('click', () => {store.dispatch({ type: 'INCREMENT' })})deBtn.addEventListener('click', () => {store.dispatch({ type: 'DECREMENT' })})// 4. 监听store中数据的变化//每次state发生变化的时候自动执行store.subscribe(() => {console.log('store数据变化了', store.getState())document.getElementById('count').innerText = store.getState().count})
</script>
</html>

2. React中使用Redux

在React中使用redux,官方要求安装俩个其他插件-ReduxToolkitreact-redux

  1. Redux Toolkit(RTK): 官方推荐编写Redux逻辑的方式,是一套工具的集合,简化书写方式
  2. react-redux:用来 链接 Redux和 React组件的中间件
npm install @reduxjs/toolkit react-redux

目录结构:新建store文件夹,将子模块放在modules目录下,index.js为store入口文件。

创建 slice 需要一个字符串名称来标识 slice,一个初始 state 值,以及一个或多个 reducer 函数来定义如何更新 state。创建 slice 后,我们可以导出生成的 Redux action creators 和整个 slice 的 reducer 函数。

/store/modules/counterStore.js

import {createSlice} from '@reduxjs/toolkit'const counterSlice = createSlice({// 标识 slice的字符串名称name:'counter',// 初始化stateinitialState:{count:0},// 修改state的方法(同步方法reducers:{increment(state,action){// 修改时的传参会放在ction.payload属性上state.count += action.payload},decrement(state,action){state.count -= action.payload}}
})// 从 counterSlice.actions中解构
export  const {increment,decrement} = counterSlice.actions
export default counterSlice.reducer

接下来,我们需要从 counter slice 中导入 reducer 函数,并将其添加到我们的 store 中。通过在 reducer 参数中定义一个字段,我们告诉 store 使用这个 slice reducer 函数来处理对该状态的所有更新。

/store/index.js

import { configureStore } from "@reduxjs/toolkit";// 导入子模块reducer
import counterReducer from "./modules/counterStore";
// 通过configureStore来创建一个store
const store =configureStore({reducer: {counter: counterReducer,},
});
export default store

提供store
导入我们刚刚创建的 Redux store,在你的 <App> 周围放一个 <Provider>,然后将 store 作为 prop 传递

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./store";// 将App组件渲染到id为root的DOM元素中
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>
);// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

读取store中的数据: 使用useSelector函数

修改store中的数据: 使用useDispatch函数,并根据需要 dispatch action

import { useDispatch, useSelector } from "react-redux";
import { increment, decrement } from "./store/modules/counterStore";
function App() {const { count } = useSelector((state) => state.counter);const dispatch = useDispatch();return (<div><button onClick={() => dispatch(decrement(1))}>-</button>{count}<button onClick={() => dispatch(increment(1))}>+</button></div>);
}export default App;

异步请求操作:

  1. 创建store的写法保持不变,配置好同步修改状态的方法
  2. 单独封装一个函数,在函数内部return一个新函数,在新函数中
    2.1 封装异步请求获取数据
    2.2 调用同步actionCreater传入异步数据生成一个action对象,并使用dispatch提交

/store/modules/sentenceStore.js

import { createSlice } from "@reduxjs/toolkit";
// 先安装npm i axios
import axios from "axios";const sentenceSlice = createSlice({name: "sentence",initialState: {sentence: {},},reducers: {setSentence(state, action) {state.sentence = action.payload;},},
});
const { setSentence } = sentenceSlice.actions;
// 获取异步请求数据
const getSentence = () => {return async (dispatch) => {const { data } = await axios.get("https://api.xygeng.cn/one");dispatch(setSentence(data.data));};
};
export { getSentence };    
export default sentenceSlice.reducer;

/store/index.js

import { configureStore } from "@reduxjs/toolkit";// 导入子模块reducer
import counterReducer from "./modules/counterStore";
import sentenceReducer from "./modules/sentenceStore";const store = configureStore({reducer: {counter: counterReducer,sentence: sentenceReducer,},
});
export default store;

3.组件中dispatch的写法保持不变

import { useDispatch, useSelector } from "react-redux";
import { increment, decrement } from "./store/modules/counterStore";
import { getSentence } from "./store/modules/sentenceStore";
import { useEffect } from "react";
function App() {const { count } = useSelector((state) => state.counter);const { sentence } = useSelector((state) => state.sentence);// 通过dispatch触发action,来更新state状态const dispatch = useDispatch();// 使用useEffect触发异步请求useEffect(() => {dispatch(getSentence());}, [dispatch]);return (<div><button onClick={() => dispatch(decrement(1))}>-</button>{count}<button onClick={() => dispatch(increment(1))}>+</button><div>{" "}{sentence.content}--{sentence.name}</div></div>);
}export default App;

👻Redux 官网教程

3. Redux调试工具

google商城里搜索:
在这里插入图片描述

在这里插入图片描述

相关文章:

【react】Redux基础用法

1. Redux基础用法 Redux 是一个用于 JavaScript 应用的状态管理库&#xff0c;它不依赖于任何 UI库&#xff0c;但常用于与 React 框架配合使用。它提供了一种集中式的状态管理方式&#xff0c;将应用的所有状态保存在一个单一的全局 Store&#xff08;存储&#xff09;中&…...

使用Python分析股票价格数据并计算移动平均线的实用指南

使用Python分析股票价格数据并计算移动平均线的实用指南 在金融市场中,移动平均线(Moving Average, MA)是一种常用的技术分析工具,用于平滑价格数据,帮助投资者识别趋势。本文将详细介绍如何使用Python分析股票价格数据,并计算移动平均线。我们将通过一个实际的案例来演…...

如何解决FPS低的问题?代码优化方法有哪些?

如果你是一名游戏开发者&#xff0c;或者对电脑性能有所追求的用户&#xff0c;那么你一定遇到过帧率&#xff08;FPS&#xff09;低的问题。帧率低会导致游戏卡顿、画面不流畅等问题&#xff0c;极大地影响了用户体验。本文将从代码层面探讨FPS低的原因&#xff0c;并提供一些…...

QT信号和槽与自定义的信号和槽

QT信号和槽与自定义的信号和槽 1.概述 这篇文章介绍下QT信号和槽的入门知识&#xff0c;通过一个案例介绍如何创建信号和槽&#xff0c;并调用他们。 2.信号和槽使用 下面通过点击按钮关闭窗口的案例介绍如何使用信号和槽。 创建按钮 在widget.cpp文件中创建按钮代码如下 …...

LC:二分查找——杂记

文章目录 268. 丢失的数字162. 寻找峰值 268. 丢失的数字 LC将此题归类为二分查找&#xff0c;并且为简单题&#xff0c;下面记一下自己对这道题目的思考。 题目链接&#xff1a;268.丢失的数字 第一次看到这个题目&#xff0c;虽然标注的为简单&#xff0c;但肯定不能直接排…...

GA/T1400视图库平台EasyCVR多品牌摄像机视频平台前端监控摄像头镜头的基础知识

在现代安全监控系统中&#xff0c;摄像机镜头作为捕捉图像的关键组件&#xff0c;其选择和应用直接影响到监控图像的质量和系统的整体性能。随着技术的发展&#xff0c;摄像机镜头的种类和功能也在不断扩展&#xff0c;以适应各种复杂的监控环境和需求。对于相机成像来讲&#…...

【C++】踏上C++的学习之旅(六):深入“类和对象“世界,掌握编程的黄金法则(一)

文章目录 前言1. "面向过程"和"面向对象"的碰撞1.1 面向过程1.2 面向对象 2. "类"的引入3. "类"的定义3.1 &#x1f349;语法展示&#xff1a;3.2 "类"的两种定义方式3.3 "类"的命名规则 4. 类的访问限定符以及封…...

【物联网技术】ESP8266 WIFI模块在STA模式下作为TCP客户端上电自动进入透传数据模式

前言:讲解如何在ESP8266 WIFI模块在STA模式下作为TCP客户端与网络调试助手(TCP服务器)上电自动进入透传数据模式,而不需重新再发指令配置进入透传模式。 演示视频: ESP8266 WIFI模块在STA模式下作为TCP客户端上电自动进入透传数据模式 wifi模块在STA模式下作为TCP客户端相…...

重构代码之用委托替代继承

在代码重构中&#xff0c;用委托替代继承 是一种用于改善代码设计和提高灵活性的重要技术。它的核心思想是&#xff0c;将子类与父类的直接继承关系转换为委托关系&#xff0c;即子类不再直接继承父类&#xff0c;而是通过持有父类的实例来访问所需的功能。 一、为什么需要用委…...

软件设计师下午题UML15分

一、涉及到的图及对应关系 二、例题 1.用例图和类图的例题 解析及答案 2.状态图和类图的例题 3.通信图和类图例题 例题...

css background-image背景图片轮播

1、CSS背景样式有以下几种&#xff1a; 背景颜色&#xff08;background-color&#xff09;&#xff1a;设置元素的背景颜色。背景图片&#xff08;background-image&#xff09;&#xff1a;设置元素的背景图片。背景重复&#xff08;background-repeat&#xff09;&#xff…...

java---认识异常(详解)

还有大家来到权权的博客~欢迎大家对我的博客提出意见哦&#xff0c;有错误会及时改进的~点击进入我的博客主页 目录 一、异常的概念及体系结构1.1 异常的概念1.2 异常的体系结构1.3异常的分类 二、异常的处理2.1防御式编程2.2 异常的抛出2.3 异常的捕获2.3.1异常声明throws2.3.…...

Linux基础学习笔记

Linux基础学习笔记 Linux目录结构&#xff1a; 具体的目录结构: /bin [重点] (/usr/bin 、 /usr/local/bin) • 是Binary的缩写, 这个目录存放着最经常使用的命令 /home [重点] • 存放普通用户的主目录&#xff0c;在Linux中每个用户都有一个自己的目录&#xff0c;一…...

自动泊车端到端算法 ParkingE2E 介绍

01 算法介绍 自主泊车是智能驾驶领域中的一项关键任务。传统的泊车算法通常使用基于规则的方案来实现。因为算法设计复杂&#xff0c;这些方法在复杂泊车场景中的有效性较低。 相比之下&#xff0c;基于神经网络的方法往往比基于规则的方法更加直观和多功能。通过收集大量专家…...

《手写Spring渐进式源码实践》实践笔记(第十七章 数据类型转换)

文章目录 第十七章 数据类型转换工厂设计实现背景技术背景Spring数据转换实现方式类型转换器&#xff08;Converter&#xff09;接口设计实现 业务背景 目标设计实现代码结构类图实现步骤 测试事先准备属性配置文件转换器工厂Bean测试用例测试结果&#xff1a; 总结 第十七章 数…...

W3C HTML 活动

关于W3C&#xff08;万维网联盟&#xff09;的HTML活动&#xff0c;我们可以从HTML的不同版本的发展历程中了解其主要的活跃时期和贡献。 HTML 2.0&#xff1a;这个版本的HTML是由Internet工程工作小组&#xff08;IETF&#xff09;的HTML工作组于1996年开发的。它是HTML的早期…...

机器学习—为什么我们需要激活函数

如果我们使用神经网络中每个神经元的线性激活函数&#xff0c;回想一下这个需求预测示例&#xff0c;如果对所有节点使用线性激活函数&#xff0c;在这个神经网络中&#xff0c;事实证明&#xff0c;这个大神经网络将变得与线性回归没有什么不同&#xff0c;所以这将挫败使用神…...

软考系统架构设计师论文:论软件的可靠性评价

试题四 论软件的可靠性评价 软件可靠性评价是软件可靠性活动的重要组成部分,既适用于软件开发过程,也可针对最 终软件系统。在软件开发过程中使用软件可靠性评价,可以使用软件可靠性模型,估计软件当前的可靠性,以确认是否可以终止测试并发布软件,同时还可以预计软件要达…...

C++:线程(thread)的创建、调用及销毁

在 C 中&#xff0c;线程的管理主要依赖于标准库 std::thread&#xff0c;自 C11 起&#xff0c;这一功能被标准化&#xff0c;使得我们能够更加方便地创建、管理和销毁线程。这里我们详细讲解线程的创建、调用和销毁流程。 1. 线程的创建 创建线程通常是为了在单独的线程中执…...

关于随身wifi,看了再决定要不要买!2024年最受欢迎的随身wifi品牌推荐!

话费、流量费缴纳起来肉疼&#xff0c;毕竟不是每个月都有很大需求&#xff0c;主打一个该省省该花花。特别是短租人群、在校学生、出差或旅游的人群、追求高性价比的人群&#xff0c;随身Wifi特别实用&#xff0c;出门当WiFi&#xff0c;在家当宽带&#xff0c;两不耽误&#…...

Ix开源平台:基于Kubernetes的私有云与家庭实验室一体化管理方案

1. 项目概述与核心价值最近在折腾一个叫Ix的开源项目&#xff0c;它来自ix-infrastructure这个组织。乍一看这个名字&#xff0c;你可能觉得有点抽象&#xff0c;但如果你对自托管、家庭实验室、私有云或者想找一个更现代、更易用的 TrueNAS 替代品感兴趣&#xff0c;那这个项目…...

VHD2VL:破解硬件描述语言转换难题的开源解决方案

VHD2VL&#xff1a;破解硬件描述语言转换难题的开源解决方案 【免费下载链接】vhd2vl 项目地址: https://gitcode.com/gh_mirrors/vh/vhd2vl 在FPGA和ASIC设计领域&#xff0c;技术团队常常面临VHDL与Verilog两种硬件描述语言之间的转换挑战。当项目需要跨语言协作、工…...

Bifrost:轻量高效的实时数据同步平台架构与实战

1. 项目概述&#xff1a;Bifrost&#xff0c;一个被低估的现代数据同步利器如果你正在处理跨数据库、跨数据源的数据同步任务&#xff0c;并且对传统ETL工具的笨重、配置复杂感到头疼&#xff0c;那么maximhq/bifrost这个项目绝对值得你花时间深入了解。我第一次接触Bifrost是在…...

轻量级配置管理框架zcf:多环境配置、敏感信息加密与云原生集成实践

1. 项目概述&#xff1a;一个面向开发者的轻量级配置管理框架最近在梳理团队内部工具链时&#xff0c;发现一个挺普遍的问题&#xff1a;不同项目、不同环境&#xff08;开发、测试、生产&#xff09;的配置管理总是乱糟糟的。.env文件满天飞&#xff0c;敏感信息一不小心就提交…...

Vibe Coding Playbook:从环境到心流,打造高效愉悦的编程系统

1. 项目概述&#xff1a;一个关于“氛围感编程”的实践指南最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“Vibe Coding Playbook”。乍一看这个标题&#xff0c;可能会有点摸不着头脑——“Vibe Coding”是什么&#xff1f;是某种新的编程范式吗&#xff1f;还是某种神…...

基于CircuitPython与ItsyBitsy M4打造可编程宏键盘:从硬件到代码全解析

1. 项目概述&#xff1a;打造你的专属输入利器 在键盘这个看似成熟的领域里&#xff0c;我们真的满足于厂商提供的“标准答案”吗&#xff1f;对于视频剪辑师、程序员、设计师或者硬核游戏玩家来说&#xff0c;一套固定的键位布局和功能&#xff0c;往往意味着效率的妥协。真正…...

Taotoken API Key精细化管理与审计日志的实际价值

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken API Key精细化管理与审计日志的实际价值 在团队协作中引入大模型能力&#xff0c;往往伴随着对资源使用安全性与可控性的…...

量子计算优化Benders分解:减少量子比特与提升收敛效率

1. 量子辅助Benders分解框架概述混合整数线性规划(MILP)在供应链管理、金融优化和资源调度等领域有着广泛应用。传统Benders分解算法通过将原问题拆分为处理整数变量的主问题(MP)和处理连续变量的子问题(SP)进行迭代求解。然而&#xff0c;随着问题规模扩大&#xff0c;主问题的…...

基于CircuitPython的电机动态性能测试系统:从原理到实践

1. 项目概述与核心价值搞电机驱动&#xff0c;最怕的就是“凭感觉”。你手上有个直流有刷电机&#xff0c;数据手册上写着空载转速12000转&#xff0c;堵转扭矩50mNm&#xff0c;但实际装到你的机器人关节或者小车上&#xff0c;带上传动机构&#xff0c;性能到底怎么样&#x…...

告别Keil!用Arduino生态玩转国产GD32芯片的3个实战技巧

用Arduino生态解锁GD32开发的三大高阶玩法 在嵌入式开发领域&#xff0c;Keil和IAR等传统工具链长期占据主导地位&#xff0c;但它们的封闭生态和复杂配置流程正在被更开放的解决方案挑战。GD32作为国产MCU的优秀代表&#xff0c;其与Arduino生态的融合为开发者提供了一条高效率…...