React hook之userReducer
在 React 中,useReducer
是一个用于管理复杂状态逻辑的 Hook,它类似于 Redux 中的 reducer 模式,但更轻量且适用于组件内部或结合 Context API 实现全局状态管理。以下是 useReducer
的详细用法指南:
1. 基本语法
const [state, dispatch] = useReducer(reducer, initialState);
reducer
:一个函数,接收当前状态和 action,返回新状态。initialState
:状态的初始值。state
:当前状态。dispatch
:用于触发状态更新的函数(发送 action)。
2. 核心概念
(1) Reducer 函数
Reducer 的格式:(state, action) => newState
action
:通常是一个对象,包含type
(操作类型)和可选的payload
(数据)。- 必须返回新状态(不可直接修改原状态!)。
function reducer(state, action) {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + 1 };case 'DECREMENT':return { ...state, count: state.count - 1 };case 'SET_VALUE':return { ...state, value: action.payload };default:return state; // 默认返回原状态}
}
(2) Dispatch Action
通过 dispatch
发送 action 来更新状态:
dispatch({ type: 'INCREMENT' });
dispatch({ type: 'SET_VALUE', payload: 42 });
3. 完整示例
计数器组件
import { useReducer } from 'react';// 定义 reducer
function counterReducer(state, action) {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };case 'DECREMENT':return { count: state.count - 1 };case 'RESET':return { count: 0 };default:return state;}
}function Counter() {const [state, dispatch] = useReducer(counterReducer, { count: 0 });return (<div><p>Count: {state.count}</p><button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button><button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button><button onClick={() => dispatch({ type: 'RESET' })}>Reset</button></div>);
}
4. 进阶用法
(1) 结合 Payload 传递数据
dispatch({ type: 'SET_NAME', payload: 'Alice' });// Reducer 处理
case 'SET_NAME':return { ...state, name: action.payload };
(2) 惰性初始化
如果初始状态需要计算,可以传入一个初始化函数:
function init(initialCount) {return { count: initialCount };
}const [state, dispatch] = useReducer(reducer, initialCount, init);
(3) 结合 Context API 实现全局状态
// 创建 Context
const CounterContext = createContext();// Provider 组件
function CounterProvider({ children }) {const [state, dispatch] = useReducer(counterReducer, { count: 0 });return (<CounterContext.Provider value={{ state, dispatch }}>{children}</CounterContext.Provider>);
}// 子组件中使用
function ChildComponent() {const { state, dispatch } = useContext(CounterContext);// ...
}
5. 与 useState
的对比
场景 | useState | useReducer |
---|---|---|
简单状态 | 适合(如布尔值、数字) | 过度设计 |
复杂状态逻辑 | 代码冗长(需多个 useState ) | 适合(逻辑集中管理) |
依赖前一个状态 | 需用函数更新(setCount(c => c + 1) ) | 自动处理(reducer 接收当前状态) |
跨组件共享状态 | 需结合 Context | 更适合(与 Context 天然搭配) |
6. 最佳实践
-
拆分 Reducer
如果逻辑复杂,可以按功能拆分成多个 reducer,再用combineReducers
(类似 Redux):function rootReducer(state, action) {return {counter: counterReducer(state.counter, action),user: userReducer(state.user, action),}; }
-
避免深层嵌套状态
尽量扁平化状态结构,便于更新。 -
异步操作
在dispatch
外处理异步逻辑(如 API 请求),完成后调用dispatch
:async function fetchData(dispatch) {const data = await api.get();dispatch({ type: 'SET_DATA', payload: data }); }
7. 示例:Todo 列表
function todoReducer(state, action) {switch (action.type) {case 'ADD_TODO':return [...state, { text: action.payload, completed: false }];case 'TOGGLE_TODO':return state.map((todo, index) =>index === action.payload? { ...todo, completed: !todo.completed }: todo);default:return state;}
}function TodoApp() {const [todos, dispatch] = useReducer(todoReducer, []);const [input, setInput] = useState('');const handleSubmit = (e) => {e.preventDefault();dispatch({ type: 'ADD_TODO', payload: input });setInput('');};return (<div><form onSubmit={handleSubmit}><input value={input} onChange={(e) => setInput(e.target.value)} /></form><ul>{todos.map((todo, index) => (<likey={index}onClick={() => dispatch({ type: 'TOGGLE_TODO', payload: index })}style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>{todo.text}</li>))}</ul></div>);
}
总结
- 何时用
useReducer
?
状态逻辑复杂、需要依赖前一个状态、或需要跨组件共享状态时。 - 优势:逻辑集中、易于测试、适合与 Context 结合。
- 注意:避免过度使用,简单场景直接用
useState
更高效。
相关文章:
React hook之userReducer
在 React 中,useReducer 是一个用于管理复杂状态逻辑的 Hook,它类似于 Redux 中的 reducer 模式,但更轻量且适用于组件内部或结合 Context API 实现全局状态管理。以下是 useReducer 的详细用法指南: 1. 基本语法 const [state, …...

Dify源码教程:账户和密码传递分析
概述 Dify系统中账户创建过程中的密码处理是Web应用安全的重要环节。本教程详细分析了从前端表单到后端存储的完整流程,展示了Dify如何安全地处理用户凭据。 前端部分 在 dify/web/app/install/installForm.tsx 文件中,当用户填写完表单并点击安装按钮…...
如果科技足够发达,是否还需要维持自然系统(例如生物多样性)中那种‘冗余’和‘多样性’,还是可以只保留最优解?
这是一个非常深刻的问题,触及到了进化生物学、复杂系统理论和未来科技哲学的交汇点。 你可以这样理解这个问题的结构: “如果科技足够发达,是否还需要维持自然系统(例如生物多样性)中那种‘冗余’和‘多样性’&#x…...

数据分析图表类型及其应用场景
说明:顶部HTML文件下载后可以直接查看,带有示图。 摘要 数据可视化作为现代数据分析的核心环节,旨在将复杂、抽象的数据转化为直观、易懂的图形形式。这种转化显著提升了业务决策能力,优化了销售与营销活动,开辟了新…...
第四十二天打卡
知识点回顾 回调函数lambda函数hook函数的模块钩子和张量钩子Grad-CAM的示例 作业:理解下今天的代码即可 # 定义一个回调函数 def handle_result(result):"""处理计算结果的回调函数"""print(f"计算结果是: {result}")# 定…...

Github 2025-06-03Python开源项目日报 Top10
根据Github Trendings的统计,今日(2025-06-03统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10Rust项目1HTML项目1C项目1 系统设计指南 创建周期:2507 天开发语言:Pyt…...
Vim查看文件十六进制方法
在 Vim 中查看文件的十六进制格式,可以通过以下步骤实现: 方法 1:使用内置命令(无需插件) 用 Vim 以二进制模式打开文件: vim -b 文件名或打开文件后执行: :set binary转换为十六进制视图&…...

电脑提示dll文件缺失怎么办 dll修复方法
当你在使用某些应用程序或启动电脑时,看到提示“DLL文件缺失”的错误信息,这通常意味着某个必要的动态链接库(DLL)文件无法被找到或加载,导致软件无法正常运行。本文将详细介绍如何排查和修复DLL文件缺失的问题&#x…...

【自动思考记忆系统】demo (Java版)
背景:看了《人工智能》中的一段文章,于是有了想法。想从另一种观点(⭕️)出发,尝试编码,告别传统程序员一段代码解决一个问题的方式。下图是文章原文和我的思考涂鸦✍️,于是想写一个自动思考记…...
【AAOS】【源码分析】用户管理(二)-- 整体架构
整体介绍 Android多用户功能作为 Android Automotive 的重要组成部分,为不同驾驶员和乘客提供了一个更加定制化、隐私保护的使用环境。Android 多用户的存在,它可以让多个用户使用同一台设备,同时保持彼此的数据、应用和设置分隔开来。 各用户类型的权限 能力SystemAdminS…...

51单片机基础部分——独立按键检测
前言 在单片机开发中,我们会经常对单片机的状态进行控制,比如我们会控制某个灯点亮,某个灯熄灭,这个时候我们就要开始做控制,我们可以通过什么控制呢,这个地方我们选择按键控制 按键实物及工作原理 生活…...

【Docker管理工具】部署Docker可视化管理面板Dpanel
【Docker管理工具】部署Docker可视化管理面板Dpanel 一、Dpanel介绍1.1 DPanel 简介1.2 主要特点 二、本次实践规划2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Dpanel镜像五、部署Dpanel…...
Github 2025-06-02 开源项目周报 Top11
根据Github Trendings的统计,本周(2025-06-02统计)共有11个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6Jupyter Notebook项目2Shell项目1Dockerfile项目1TypeScript项目1Vue项目1PowerShell项目1MindsDB:定制企业数据人工智能的开源平台…...

springboot实现查询学生
文章目录 数据库前端 请求mybatis 数据库 前端 请求 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <a href"/list">启动学生管理…...
深入解析C++五大常用设计模式:原理、实现与应用场景
设计模式是解决特定软件设计问题的经典方案,掌握它们能显著提升代码的可维护性和扩展性。本文详细解析C中五种最常用的设计模式,附带完整代码示例和实战技巧。 一、设计模式概述 设计模式是面向对象编程中可复用的解决方案,它们源于工程师们…...
标识符Symbol和迭代器的实现
Symbol基础 Symbol("描述") 创建唯一标识符(每次调用返回新值) Symbol.for("key") 全局注册表模式(相同key返回同一Symbol) Symbol特性 作为对象属性键时:obj[SymbolKey] value不参与常规遍历&…...

Appium+python自动化(九)- 定位元素工具
简介 环境搭建好了,其他方面的知识也准备的差不多了,那么就开始下一步元素定位,元素定位主要介绍如何使用uiautomatorviewer,通过定位到页面上的元素,然后进行相应的点击等操作. 此外在介绍另一款工具:Insp…...

Unity 中实现可翻页的 PageView
之前已经实现过: Unity 中实现可复用的 ListView-CSDN博客文章浏览阅读5.6k次,点赞2次,收藏27次。源码已放入我的 github,地址:Unity-ListView前言实现一个列表组件,表现方面最核心的部分就是重写布局&…...
clickhouse常用语句汇总——持续更新中
一、查询判断是否包含指定列 1.根据数据库,表名查看表包含的列 SELECT name FROM system.columns WHERE table table_name AND database databasename;2.查找指定列target_column是否是表table_name的列 SELECT count() > 0 AS column_exists FROM system…...

云计算 Linux Rocky day05【rpm、yum、history、date、du、zip、ln】
云计算 Linux Rocky day05【rpm、yum、history、date、du、zip、ln】 目录 云计算 Linux Rocky day05【rpm、yum、history、date、du、zip、ln】1.RPM包的一般安装位置2.软件名和软件包名3.查询软件信息4.查询软件包5.导入红帽签名信息,解决查询软件包信息报错6.利用…...

LuaJIT2.1 和 Lua5.4.8 性能对比
说明 最近在学习 LuaJIT,想看看把它接入到项目中使用,会提高多大的性能。 今天抽时间,简单地测试了一下 LuaJIT 2.2 和 Lua5.4.8 的性能。 测试平台: 系统:Windows 10 WSLCPU:Intel Core™ i7-8700 CPU…...
深度学习姿态估计实战:基于ONNX Runtime的YOLOv8 Pose部署全解析
本文将详细介绍如何脱离YOLO官方环境,使用ONNX Runtime部署YOLOv8姿态估计模型。内容包括模型加载、图像预处理(Letterbox缩放和填充)、推理执行、输出解码(边界框和关键点处理)、非极大值抑制(NMS…...
深度探索:如何用DeepSeek重构你的工作流
前言:AI时代的工作革命 在人工智能浪潮席卷的今天,DeepSeek作为国产大模型的代表之一,正以其强大的自然语言处理能力、代码生成能力和多模态交互特性,重新定义着人类的工作方式。根据IDC报告显示,2024年企业级AI应用市场规模已突破800亿美元,其中智能办公场景占比达32%,…...

深入解析与解决方案:处理Elasticsearch中all found copies are either stale or corrupt未分配分片问题
目录 引言 1 问题诊断深入分析 1.1 错误含义深度解析 1.2 获取详细的诊断信息 2 解决方案选择与决策流程 2.1 可用选项全面对比 2.2 推荐处理流程与决策树 3 具体操作步骤详解 3.1 优先尝试 - 分配最新副本(最低风险) 3.2 中等风险方案 - 分配…...

【NLP 78、手搓Transformer模型结构】
你以为走不出的淤泥,也迟早会云淡风轻 —— 25.5.31 引言 ——《Attention is all you need》 《Attention is all you need》这篇论文可以说是自然语言处理领域的一座里程碑,它提出的 Transformer 结构带来了一场技术革命。 研究背景与目标 在 Transfo…...
yum更换阿里云的镜像源
步骤 1:备份原有源配置(重要!) sudo mkdir /etc/yum.repos.d/backup sudo mv /etc/yum.repos.d/CentOS-* /etc/yum.repos.d/backup/步骤 2:下载阿里云源配置 sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https:…...

如何自定义WordPress主题(5个分步教程)
如果您已经安装了一个 WordPress 主题,但它不太适合您,您可能会感到沮丧。在定制 WordPress 主题方面,您有很多选择。 挑战在于找到正确的方法。 在本篇文章中,我将引导您了解自定义 WordPress 主题的各种选项,帮助您…...
ios版本的Tiktok二次安装不上,提示:Unable to Install “TikTok”
问题:Domain: IXUserPresentableErrorDomain Code: 1 Recovery Suggestion: Failed to load Info.plist from bundle at path /private/var/containers/Bundle/Application/E99D86D4-F96E-48F9-86C5-FE095A22E13A/DouyinDev.app/PlugIns/AwemeNotificationService.a…...

react实现markdown文件预览
文章目录 react实现markdown文件预览1、实现md文件预览2、解决图片不显示3、实现效果 react实现markdown文件预览 1、实现md文件预览 1️⃣第一步:安装依赖: npm install react-markdown remark-gfmreact-markdown:将 Markdown 渲染为 Rea…...
Neo4j 认证与授权:原理、技术与最佳实践深度解析
Neo4j 作为领先的图数据库,其安全机制——认证(Authentication)与授权(Authorization)——是保障数据资产的核心防线。本文将深入剖析其工作原理、关键技术、实用技巧及行业最佳实践,助您构建坚不可摧的图数据安全体系。 Neo4j 提供了强大且灵活的认证授权框架,涵盖从基…...