【React】状态管理之Redux


🌈个人主页: 鑫宝Code
🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础
💫个人格言: "如无必要,勿增实体"
文章目录
- 状态管理之Redux
- 引言
- 1. Redux 的核心概念
- 1.1 单一数据源(Single Source of Truth)
- 1.2 State 是只读的
- 1.3 使用纯函数执行修改
- 2. Redux 工作流程
- 2.1 数据流向
- 2.2 中间件机制
- 3. Redux 内部实现原理
- 3.1 createStore 的实现
- 3.2 combineReducers 的实现
- 4. Redux 性能优化
- 4.1 reselect 的使用
- 4.2 不可变性的保持
- 5. 实际应用中的最佳实践
- 5.1 Action 创建函数
- 5.2 异步 Action 处理
- 总结
状态管理之Redux
引言
Redux 作为一个优秀的状态管理工具,在 React 生态系统中占据着重要地位。本文将深入探讨 Redux 的核心工作原理,帮助开发者更好地理解和使用这个工具。
1. Redux 的核心概念
1.1 单一数据源(Single Source of Truth)
Redux 使用单一的 store 来存储应用的所有状态。这意味着:
- 整个应用的状态被存储在一个对象树中
- 这个对象树只存在于唯一的 store 中
- 状态是只读的,唯一改变状态的方式是触发 action
const store = {todos: [],visibilityFilter: 'SHOW_ALL',user: {id: null,name: null}
}
1.2 State 是只读的
在 Redux 中,改变状态的唯一方式是触发(dispatch)一个 action。这确保了:
- 视图和网络请求都不能直接修改状态
- 所有的修改都被集中化处理
- 修改都是按顺序一个接一个地执行
// Action 的结构
const action = {type: 'ADD_TODO',payload: {text: '学习 Redux',completed: false}
}
1.3 使用纯函数执行修改
Reducer 是一个纯函数,它接收先前的状态和一个 action,返回新的状态:
const todoReducer = (state = [], action) => {switch (action.type) {case 'ADD_TODO':return [...state, action.payload]case 'TOGGLE_TODO':return state.map(todo =>todo.id === action.payload.id? { ...todo, completed: !todo.completed }: todo)default:return state}
}
2. Redux 工作流程
2.1 数据流向
Redux 采用严格的单向数据流,主要包含以下步骤:
- 用户在界面触发事件
- 调用 dispatch(action)
- Redux store 调用 reducer 函数
- Root reducer 把多个子 reducer 输出合并成一个单一的状态树
- Redux store 保存了 reducer 返回的完整状态树
2.2 中间件机制
中间件提供了一个分类处理 action 的机制:
// 中间件示例
const logger = store => next => action => {console.log('dispatching', action)let result = next(action)console.log('next state', store.getState())return result
}
3. Redux 内部实现原理
3.1 createStore 的实现
createStore 是 Redux 最核心的 API:
function createStore(reducer, preloadedState, enhancer) {let currentReducer = reducerlet currentState = preloadedStatelet currentListeners = []function getState() {return currentState}function subscribe(listener) {currentListeners.push(listener)return function unsubscribe() {const index = currentListeners.indexOf(listener)currentListeners.splice(index, 1)}}function dispatch(action) {currentState = currentReducer(currentState, action)currentListeners.forEach(listener => listener())return action}return {getState,subscribe,dispatch}
}
3.2 combineReducers 的实现
combineReducers 用于合并多个 reducer:
function combineReducers(reducers) {return function combination(state = {}, action) {const nextState = {}let hasChanged = falsefor (let key in reducers) {const reducer = reducers[key]const previousStateForKey = state[key]const nextStateForKey = reducer(previousStateForKey, action)nextState[key] = nextStateForKeyhasChanged = hasChanged || nextStateForKey !== previousStateForKey}return hasChanged ? nextState : state}
}
4. Redux 性能优化
4.1 reselect 的使用
使用 reselect 可以避免不必要的重复计算:
import { createSelector } from 'reselect'const getTodos = state => state.todos
const getVisibilityFilter = state => state.visibilityFilterconst getVisibleTodos = createSelector([getTodos, getVisibilityFilter],(todos, filter) => {switch (filter) {case 'SHOW_ALL':return todoscase 'SHOW_COMPLETED':return todos.filter(t => t.completed)case 'SHOW_ACTIVE':return todos.filter(t => !t.completed)}}
)
4.2 不可变性的保持
确保状态更新的不可变性是 Redux 性能优化的关键:
// 不推荐
state.todos[0].completed = true// 推荐
return {...state,todos: state.todos.map((todo, index) =>index === 0 ? { ...todo, completed: true } : todo)
}
5. 实际应用中的最佳实践
5.1 Action 创建函数
使用 action 创建函数来生成 action:
const addTodo = text => ({type: 'ADD_TODO',payload: {id: nextTodoId++,text,completed: false}
})
5.2 异步 Action 处理
使用 redux-thunk 处理异步操作:
const fetchTodos = () => {return async dispatch => {dispatch({ type: 'FETCH_TODOS_REQUEST' })try {const response = await api.fetchTodos()dispatch({type: 'FETCH_TODOS_SUCCESS',payload: response.data})} catch (error) {dispatch({type: 'FETCH_TODOS_FAILURE',error: error.message})}}
}
总结
Redux 通过其简单而强大的设计原则,为 React 应用提供了可预测的状态管理能力。理解其工作原理对于构建大型应用至关重要。核心要点包括:
- 单一数据源
- 状态只读
- 使用纯函数进行修改
- 单向数据流
- 中间件机制
通过合理运用这些原则,我们可以构建出更加可维护和可扩展的应用。同时,通过使用 reselect、保持不可变性等优化手段,还能确保应用具有良好的性能表现。

相关文章:

【React】状态管理之Redux
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 状态管理之Redux引言1. Redux 的核心概念1.1 单一数据源(Single Sou…...

3195. 有趣的数-13年12月CCF计算机软件能力认证(组合数)
题目 思路 统计方案的时候先去分类,先放01,然后在考虑23对于第k类, 对于01的选择 对于所有的分类:本题我觉得要考虑的几个点就是:状态分类得到数学公式组合数的计算防越界处理 代码 计算组合数的代码模板࿱…...

基于 Python 的 Bilibili 评论分析与可视化
一、项目概述 本项目利用 Python 对 Bilibili (哔哩哔哩)平台上的视频评论数据进行爬取、清洗和分析,并通过可视化展示数据的主要特征。我们通过以下几个步骤实现了这一过程: 数据爬取:使用 Bilibili 提供的 API 获取…...

大语言模型理论基础
文章目录 前言大语言模型必需知识概述大语言模型目标模型上下文神经网络的神经元常见激活函数SigmoidTanhRelusoftmax 通用近似定理多层感知机(MLP)拟合最后 前言 你好,我是醉墨居士,我们接下来对大语言模型一探究竟,…...

【 LLM论文日更|检索增强:大型语言模型是强大的零样本检索器 】
论文:https://aclanthology.org/2024.findings-acl.943.pdf代码:GitHub - taoshen58/LameR机构:悉尼科技大学 & 微软 & 阿姆斯特丹大学 & 马里兰大学领域:retrieval & llm发表:ACL2024 研究背景 研究…...
【基于轻量型架构的WEB开发】课程 作业3 Spring框架
一. 单选题(共12题,48分) 1. (单选题)以下有关Spring框架优点的说法不正确的是( )。 A. Spring就大大降低了组件之间的耦合性。 B. Spring是一种侵入式框架 C. 在Spring中,可以直接通过Spring配置文件管理…...

14.最长公共前缀-力扣(LeetCode)
题目: 解题思路: 解决本题的关键点是确定扫描的方式,大体上有两种方式:横向扫描和纵向扫描。 1、横向扫描:首先比较第一个字符串和第二个字符串,记录二者的公共前缀,然后用当前公共前缀与下一个…...

客户案例|智能进化:通过大模型重塑企业智能客服体验
01 概 述 随着人工智能技术的快速发展,客户对服务体验的期待和需求不断升级。在此背景下,大模型技术的崛起,为智能客服领域带来了创造性的变革。 在上篇文章《在后LLM时代,关于新一代智能体的思考》中有提到,智能客服…...
Flink Job更新和恢复
Checkpoints 的主要目的是为意外失败的作业提供恢复机制。 Savepoints的设计更侧重于可移植性和操作灵活性,尤其是在 job 变更方面。Savepoint 的用例是针对计划中的、手动的运维。例如,可能是更新你的 Flink 版本,更改你的作业图等等。 fli…...
读多写少业务中,MySQL如何优化数据查询方案?
小熊学Java站点:https://www.javaxiaobear.cn 编程资料合集:https://pqgmzk7qbdv.feishu.cn/base/QXq2bY5OQaZiDksJfZMc30w5nNb?from=from_copylink 看一看当面试官提及“在读多写少的网络环境下,MySQL 如何优化数据查询方案”时,你要从哪些角度出发回答问题??? 案例…...

Bugku CTF_Web——点login咋没反应
Bugku CTF_Web——点login咋没反应 进入靶场 随便输个试试 看来确实点login没反应 抓包看看 也没有什么信息 看了下源码 给了点提示 一个admin.css try ?12713传参试试 拿到一个php代码 <?php error_reporting(0); $KEYctf.bugku.com; include_once("flag.php&q…...

attention 注意力机制 学习笔记-GPT2
注意力机制 这可能是比较核心的地方了。 gpt2 是一个decoder-only模型,也就是仅仅使用decoder层而没有encoder层。 decoder层中使用了masked-attention 来进行注意力计算。在看代码之前,先了解attention-forward的相关背景知识。 在普通的self-atten…...
什么是HTTP,什么是HTTPS?HTTP和HTTPS都有哪些区别?
什么是 HTTP? HTTP(Hypertext Transfer Protocol,超文本传输协议)是一种应用层协议,用于在互联网上进行数据通信。它定义了客户端(通常是浏览器)和服务器之间的请求和响应格式。HTTP 是无状态的…...

SkyWalking-安装
SkyWalking-简单介绍 是一个开源的分布式追踪系统,用于检测、诊断和优化分布式系统的功能。 支持 ElasticSearch、H2、MySQL、PostgreSql 等数据库 基于 ElasticSearch 的情况 ElasticSearch(ES) 安装 1、下载并解压 https://www.elastic…...

RabbitMQ运维
1. 单机多节点 1.1 搭建RabbitMQ ①安装RabbitMQ 略 ②确认RabbitMQ运⾏没问题 #查看RabbitMQ状态 rabbitmqctl status 节点名称: 端口号: 25672:Erlang分布式节点通信的默认端⼝, Erlang是RabbitMQ的底层通信协议.15672: Web管理界⾯的默认端⼝, 通过这个端⼝可以访问R…...
Go语言并发精髓:深入理解和运用go语句
Go语言并发精髓:深入理解和运用go语句 在Go语言的世界里,go语句是实现并发的核心,它简洁而强大,允许程序以前所未有的方式运行多个任务。本文将深入探讨go语句及其执行规则,揭示Go语言并发编程的内在机制,并提供实际案例帮助读者掌握其用法。 1. go语句的基本概念(Wha…...

基于STM32的智能家居系统:MQTT、AT指令、TCP\HTTP、IIC技术
一、项目概述 随着智能家居技术的不断发展,越来越多的家庭开始使用智能设备来提升生活质量和居住安全性。智能家居系统不仅提供了便利的生活方式,还能有效地监测家庭环境,保障家庭安全。本项目以设计一种基于STM32单片机的智能家居系统为目标…...

分糖果(相等分配)
题目:有n种不同口味的糖果,第i种糖果的数量为a[i],现在需要把糖果分给m个人。分给每个人糖果的数量必须是相等的,并且每个人只能选择一种糖果。也就是说,可以把一种糖果分给多个人,但是一个人的糖果不能有多…...
docker构建jdk11
# 建立一个新的镜像文件,配置模板:新建立的镜像是以centos为基础模板 # 因为jdk必须运行在操作系统之上 FROM centos:7.9.2009# 作者名 MAINTAINER yuanhang# 创建一个新目录来存储jdk文件 RUN mkdir /usr/local/java#将jdk压缩文件复制到镜像中&#…...
唐帕科技校园语音报警系统:通过关键词识别,阻止校园霸凌事件
校园霸凌问题已成为全球教育领域的严峻挑战,给受害者带来了身心上的长期创伤。然而,随着科技的发展,尤其是人工智能和语音识别技术的不断进步,我们开始看到创新性解决方案的出现。校园语音报警系统便是其中一种利用技术手段保护学…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...

Ray框架:分布式AI训练与调参实践
Ray框架:分布式AI训练与调参实践 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 Ray框架:分布式AI训练与调参实践摘要引言框架架构解析1. 核心组件设计2. 关键技术实现2.1 动态资源调度2.2 …...
关于疲劳分析的各种方法
疲劳寿命预测方法很多。按疲劳裂纹形成寿命预测的基本假定和控制参数,可分为名义应力法、局部应力一应变法、能量法、场强法等。 1名义应力法 名义应力法是以结构的名义应力为试验和寿命估算的基础,采用雨流法取出一个个相互独立、互不相关的应力循环&…...

Ubuntu 安装 Mysql 数据库
首先更新apt-get工具,执行命令如下: apt-get upgrade安装Mysql,执行如下命令: apt-get install mysql-server 开启Mysql 服务,执行命令如下: service mysql start并确认是否成功开启mysql,执行命令如下&am…...
如何让非 TCP/IP 协议驱动屏蔽 IPv4/IPv6 和 ARP 报文?
——从硬件过滤到协议栈隔离的完整指南 引言 在现代网络开发中,许多场景需要定制化网络协议(如工业控制、高性能计算),此时需确保驱动仅处理特定协议,避免被标准协议(如 IPv4/IPv6/ARP)干扰。本文基于 Linux 内核驱动的实现,探讨如何通过硬件过滤、驱动层拦截和协议栈…...