React setState 连续调用「丢更新」排查:批量更新与函数式更新
📅 2026/7/21 13:41:25
👁️ 次浏览
React setState 连续调用「丢更新」排查:批量更新与函数式更新写 React 时你大概率遇到过这种诡异现象:一个按钮里连着调三次setCount(count 1),点一下却只加了 1,不是 3。或者刚setState完立刻读 state,值还是旧的。这不是 React 的 bug,而是「批量更新」和「闭包快照」两个机制在起作用。搞懂它们,这类问题就再也不会困扰你。一、复现「加 3 变加 1」import { useState } from react; function Counter() { const [count, setCount] useState(0); const handleClick () { // 直觉以为会 3,实际只 1 setCount(count 1); setCount(count 1); setCount(count 1); }; return button onClick{handleClick}count {count}/button; }点一下,count 从 0 变成 1,不是 3。为什么?二、根因:count 是这次渲染的「快照」,三次算的是同一个值关键点:count不是一个会实时变化的变量,而是本次渲染被「冻结」的值。在这次点击的事件函数里,count自始至终都是0。所以三行代码实际上是:setCount(0 1); // 请求把 count 设成 1 setCount(0 1); // 请求把 count 设成 1 setCount(0 1); // 请求把 count 设成 1三次都是「把 count 设成 1」,React 又把同一次事件里的多个 setState 合并成一次渲染(这就是批量更新 / batching),最终结果自然是 1。顺带解决另一个高频困惑——setState后立刻读不到新值:const handleClick () { setCount(count 1); console.log(count); // 打印的还是 0!不是 1 };因为count是快照,setCount只是「预约下次渲染用新值」,不会就地改掉当前这个count变量。想拿新值,得等下一次渲染。三、正确写法:用函数式更新当新值依赖旧值时,别传具体值,传一个函数。React 会把这些函数排队,依次拿「上一个的结果」当入参:const handleClick () { // updater 收到的 prev 是队列里累积后的最新值 setCount((prev) prev 1); // 0 - 1 setCount((prev) prev 1); // 1 - 2 setCount((prev) prev 1); // 2 - 3 };这次点一下就是 3。记住判断标准:新 state 依赖旧 state 时,一律用setX(prev ...),不要用setX(当前变量 1)。四、React 18 之后,异步回调里也批量了React 17 有个坑:只有 React 事件(onClick 等)里的 setState 才批量,setTimeout、fetch().then这类异步回调里的 setState 是逐个触发渲染的,连着 set 三个 state 会渲染三次。React 18 引入自动批量(automatic batching),异步回调里也统一批量了:const load async () { const res await fetch(/api/data); const data await res.json(); // React 18:下面两个 setState 合并成一次渲染 setLoading(false); setData(data); // React 17:这里会渲染两次 };这是升级 React 18 后行为变化的常见来源。绝大多数情况批量是好事(少一次渲染),个别真需要「立即单独刷新」的场景,可以用flushSync强制同步:import { flushSync } from react-dom; flushSync(() setLoading(false)); // 立刻渲染,不与后面合并 doSomethingThatReadsDOM();flushSync是逃生舱,别滥用——它会牺牲批量带来的性能优势。五、对象/数组 state 的连带坑同样的快照逻辑,套在对象上还多一个「必须换新引用」的坑:const [user, setUser] useState({ name: , age: 0 }); // 错误:直接改属性,引用没变,React 认为没更新,不重渲染 const bad () { user.age 18; setUser(user); }; // 正确:展开出新对象,基于 prev 计算 const good () { setUser((prev) ({ ...prev, age: 18 })); };要点:React 用Object.is比较新旧引用来决定要不要重渲染,原地修改属性引用不变,界面就不刷新。始终返回新对象。小结state 是每次渲染被冻结的快照,同一个事件里count始终是旧值,setState后立刻读也是旧值。新值依赖旧值就用函数式更新setX(prev ...),别用setX(变量 1)连写。React 18 起异步回调也自动批量;需要立即单独渲染用flushSync(逃生舱,慎用)。对象/数组 state 必须返回新引用,原地改属性不会触发重渲染。一句话记住:setState 不是「立刻改变量」,是「预约下次渲染的值」;依赖旧值时永远用函数式更新。
1. 项目概述与核心价值在嵌入式系统开发中,I2C总线因其简洁的两线制(SDA、SCL)和主从多设备架构,成为了连接传感器、EEPROM、RTC等低速外设的首选协议。然而,当数据吞吐量增大或系统实时性要求提高时,传统的…
📅 2026/7/21 13:41:25
AI智能魔镜:如何通过面部识别与语音交互打造专业级智能家居中枢? 【免费下载链接】AI-Smart-Mirror Smart Mirror with a smart AI 🤖 项目地址: https://gitcode.com/gh_mirrors/ai/AI-Smart-Mirror
在智能家居技术快速发展的今天&am…
📅 2026/7/21 13:41:25
PhotoGIMP深度解析:如何让GIMP拥有Photoshop的流畅体验 【免费下载链接】PhotoGIMP A Patch for GIMP 3 for Photoshop Users 项目地址: https://gitcode.com/GitHub_Trending/ph/PhotoGIMP
还在为GIMP的复杂界面而困扰?PhotoGIMP为您提供了一个革…
📅 2026/7/21 13:41:25
信号格满格却打不开网页,那种绝望谁懂?特别是去川西或者西藏自驾,手机直接变砖头。以前我觉得卫星通信是军方或者富豪玩的,直到去年夏天,我和几个驴友在色达外围迷路,手机彻底没信号,那一刻我才意识到,在这个万物互联的时代,离线等于失联,而失联意味着危险。当时我们…
📅 2026/7/21 20:42:13
多账号管理浏览器的内存占用本质上由 Chromium 多进程架构决定,每个独立环境都会拉起浏览器进程、GPU 进程与渲染进程,单环境到多环境呈近似线性增长。云手机是真实 Android 实例,需要额外承载虚拟化层、系统服务与常驻进程,整体资…
📅 2026/7/21 20:41:58
编号 类型 领域 问题【含材料科学】 问题的数学分析(含定理/理论/集成电路/数字逻辑电路/数学物理/数学化学/材料物理/材料科学/其他) 参数列表及参数的数值设计及范围及边界条件 关联知识 1 技术演进分析 集成电路 / 数字逻辑电路 RTL (Resistor-Transistor Logic…
📅 2026/7/21 20:41:58
1. 数据结构中的树形结构概述在计算机科学领域,树形结构是最基础也是最重要的数据结构之一。作为一名从业十余年的软件工程师,我处理过无数与树相关的算法问题,从简单的二叉树遍历到复杂的红黑树实现。树之所以如此重要,是因为它完…
📅 2026/7/21 20:41:58
1. 项目概述:为什么我们需要一个XSS靶场?如果你是一名Web安全爱好者、渗透测试初学者,或者是一名希望加固自己应用的前后端开发者,那么“XSS-Labs”这个名字你一定不陌生。它不是一个商业产品,而是一个在安全圈内流传甚…
📅 2026/7/21 20:41:58
1. 项目概述:为什么需要游戏翻译插件?如果你是一个Unity游戏开发者,或者是一个喜欢玩各种独立游戏的玩家,大概率遇到过这样的场景:一款玩法精良、美术出色的游戏,因为语言不通而让人望而却步。尤其是那些由…
📅 2026/7/21 20:41:58
本文关键词:geo geo测试你是不是也遇到过这种奇葩事?明明你的网站内容写得比同行好,图片更清晰,甚至价格还更低,但在搜索结果里就是排不进去。特别是做本地生意的老板,那种看着隔壁老王明明啥也不是,却天天坐在收银台数钱的滋味,真的憋屈。我最近为了搞懂这个所谓的“地…
📅 2026/7/21 0:00:39
1. Octane Render与C4D的黄金组合:为什么选择这个方案?在三维创作领域,渲染器的选择往往决定了作品的最终呈现质量和工作效率。作为Cinema 4D(C4D)用户,Octane Render的GPU加速特性与实时预览功能ÿ…
📅 2026/7/21 0:00:41
1. GPMC接口设计:从硬件连接到软件配置的全局视角在嵌入式系统开发中,尤其是基于TI Sitara系列如AM263x这类高性能微控制器的项目里,外部存储器的扩展几乎是绕不开的一环。无论是存放大量非易失性代码的NOR Flash,还是作为高速数据…
📅 2026/7/21 0:00:41
1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…
📅 2026/7/21 1:04:03
1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…
📅 2026/7/21 1:04:03
更多请点击:
https://intelliparadigm.com
第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…
📅 2026/7/21 1:04:03
目录
第一步:选对模板,省心一半
第二步:打开扫码点餐功能
开启功能按钮
桌台管理与桌码生成
第三步:个性化设计,打造品牌感
调整点餐页面
设置点餐规则 你还在让顾客站着排队点餐吗?2025年ÿ…
📅 2026/7/21 7:04:23
在业务中快速构建一个能理解私有文档、准确回答专业问题的智能助手,是很多开发团队面临的共同挑战。传统方案往往需要从零开始搭建复杂的 RAG(检索增强生成)系统,涉及文档解析、向量化、检索、大模型调用等多个环节,整…
📅 2026/7/21 17:04:52
FAE放射组学分析工具:医学影像特征探索的完整解决方案 【免费下载链接】FAE FeAture Explorer 项目地址: https://gitcode.com/gh_mirrors/fae/FAE
你是否曾经面对海量医学影像数据感到无从下手?想要从CT、MRI等影像中提取有价值的定量特征&#…
📅 2026/7/21 5:04:16