【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压缩文件复制到镜像中&#…...
唐帕科技校园语音报警系统:通过关键词识别,阻止校园霸凌事件
校园霸凌问题已成为全球教育领域的严峻挑战,给受害者带来了身心上的长期创伤。然而,随着科技的发展,尤其是人工智能和语音识别技术的不断进步,我们开始看到创新性解决方案的出现。校园语音报警系统便是其中一种利用技术手段保护学…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
