
本文探讨react 18中,当多个独立事件(如onmousedown和onfocus)在短时间内触发状态更新时,setstate回调函数可能被多次执行的现象。我们将分析react的事件批处理机制,特别是其不跨越不同意图事件的特性,以及如何通过丢弃陈旧结果来确保最终状态的一致性,强调updater函数纯粹性的重要性。
在React应用开发中,我们通常期望setState的更新函数(updater function)在一次状态更新周期中只被执行一次。然而,在特定场景下,尤其是在React 18的自动批处理机制下,当多个“有意图的事件”(intentional events)在短时间内连续触发状态更新时,我们可能会观察到setState的更新函数被多次执行,即使没有开启严格模式(Strict Mode)。这种行为可能导致开发者困惑,但实际上是React内部机制为了确保状态一致性而采取的策略。
考虑以下React组件代码,其中包含两个状态state和state2,并通过useEffect和onFocus事件处理器触发setState更新:
import React, { useState, useEffect, useRef } from "react";
import "./styles.css";
function App() {
const [state, setState] = useState([]);
const [state2, setState2] = useState(0);
// 用于记录渲染迭代次数
const render = useRef(0);
render.current++;
useEffect(() => {
if (state2) {
console.log(render.current, performance.now(), "effect");
setState(s => {
console.log(render.current, performance.now(), "effect setState", s);
return [...s, "effect"];
});
}
}, [state2]);
return (
<input
onMouseDown={() => {
console.log(render.current, performance.now(), "mousedown");
setState2(1);
}}
onFocus={() => {
console.log(render.current, performance.now(), "focus");
setState(s => {
console.log(render.current, performance.now(), "focus setState", s);
return [...s, "focus"];
});
}}
/>
);
}当用户点击元素时,onMouseDown事件会先于onFocus事件触发。我们期望的控制台输出可能是:
effect focus effect setState [] focus setState ['effect']
然而,实际的控制台输出(可能略有不同,但核心行为一致)会是:
1 2971 "mousedown" 2 2974 "effect" 2 2978 "focus" 3 2978 "focus setState" [] // 第一次执行,基于旧的state 4 2982 "effect setState" [] 4 2982 "focus setState" (1) ["effect"] // 第二次执行,基于更新后的state
从上述输出中可以看到,"focus setState"的日志出现了两次,其中第一次的s是空数组[],而第二次的s是['effect']。这表明onFocus中的setState更新函数被执行了两次,并且第二次执行时接收到了由useEffect更新后的正确状态。
要理解这一现象,关键在于React 18的自动批处理(Automatic Batching)机制以及其对“有意图的事件”的处理。
美图云修
商业级AI影像处理工具
52
查看详情
在我们的例子中:
由于onMouseDown和onFocus是独立的事件,React可能在处理onFocus事件的更新队列时,state2的更新及其导致的useEffect中的setState尚未完全提交到DOM。
结合日志中的渲染迭代次数和时间戳,我们可以更清晰地追踪执行流程:
这种行为与严格模式下setState updater函数被执行两次(并丢弃第二次结果)有相似之处,但其根本原因不同。严格模式是为了帮助开发者发现不纯的副作用,而这里则是React为了在复杂的并发更新和事件边界下,确保最终状态的一致性,通过重新执行updater函数来基于最新的状态进行计算。
总之,当你在React 18中观察到setState的updater函数被多次执行时,不必惊慌。这通常是React为了保证状态一致性而采取的内部优化策略,尤其是在多个独立事件触发更新的场景下。关键在于始终遵循React的函数式编程范式,确保updater函数的纯粹性。
以上就是深入理解React setState回调的多次执行:事件批处理与状态一致性的详细内容,更多请关注其它相关文章!
# 两次
# SEO 商店
# 如何开礼品网站推广店铺
# seo在哪里发帖
# 人设营销推广方案模板
# 电话营销推广合同怎么写
# 布吉企业免费网站建设
# sem关键词的成交流程排名
# 彩票seo综合查询
# 营销推广有哪些公司做
# 炒米粉如何营销推广
# 是在
# 这一
# css
# 如何使用
# 美图
# 新和
# 迭代
# 多个
# 回调
# 批处理
# 应用开发
# 回调函数
# app
# 处理器
# react
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
酷狗音乐多音轨设置教程
Golang中的rune与byte类型区别是什么_Golang字符与字节处理详解
网页版网易云音乐入口_网易云音乐在线官网登录
钉钉任务无法提醒如何处理 钉钉任务提醒优化方法
学习通网页版课程打不开_课程无法访问时的解决方法
CodeIgniter 3 中基于 MySQL 数据高效生成动态图表教程
todesk如何添加信任设备_todesk信任设备设置教程
《百度畅听版》关闭兴趣推荐方法
电子白板帮助菜单使用指南
《植物大战僵尸3》火龙草作用介绍
Google Drive API服务器端访问指南:服务账户认证详解
一点万象签到领积分指南
c++如何实现一个简单的RPC框架_c++远程过程调用原理与实践
百度地图离线地图无法加载如何解决 百度地图离线地图加载优化方法
《淘宝联盟》推广自己的店铺方法
Python对象引用与属性赋值:理解链表中的行为
电脑双系统如何安装和卸载 Windows和Linux双系统安装教程【详解】
CodeIgniter 3 连接 SQL Server:正确获取查询结果的教程
《气泡星球》兑换码礼包大全
如何在Podman容器中运行Composer_Docker替代品Podman的PHP与Composer容器化实践
《撕歌》会员开通方法
《雷电模拟器》自动点击设置方法
《360浏览器》设置摄像头权限方法
有道AI翻译入口 智能写作官方网站入口
HTML Canvas文本样式定制指南:解决外部字体加载与应用难题
PPT智能排版生成入口 免费PPT内容自动生成平台
《随手记》关闭首页消息推送方法
在Django单元测试中优雅处理信号:基于环境的条件执行策略
Composer reinstall命令重装损坏的包
LINUX怎么查看显卡信息_LINUX查看GPU状态
德邦快递收费标准详解
百度竞价WAP显示PC链接问题
修复UI元素交互障碍:从“开始”按钮到信息框的平滑过渡实现
如何在vscode中关闭it环境
猫眼app抢票快还是小程序快
如何在CSS中清除浮动解决背景颜色不包裹内容问题_clear after技巧
网站体验不好=浪费钱:如何提升-用户体验效果差
抄漫画官网防走失地址_抄漫画最新漫画完整版阅读入口
高德地图导航路线偏差报警频繁怎么办 高德地图路线偏差修复与优化方法
Excel宏怎么删除_Excel中删除宏的详细操作流程
苹果手机手电筒无法开启
百度识图图像分析 百度识图识别平台
CSS布局中意外顶部空白的调试与解决:深入理解padding-top
秋风萧瑟洪波涌起中的萧瑟指的是什么
TikTok网页版入口快速访问 TikTok官网账号登录方法
Win11如何分屏操作_Win11多窗口分屏技巧
获取WooCommerce产品在后台编辑页面的分类ID
《战地6》反作弊已成功拦截240万次作弊 发售第一周98%比赛没有作弊
键盘声音异常怎么回事_键盘异响怎么处理
c++如何使用std::thread::join和detach_c++线程生命周期管理
2025-12-13
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。