React 状态、身份与副作用
React 的一次渲染是输入快照到界面描述的纯计算,状态属于树中的身份,Effect 则让已经提交的界面与外部世界同步。更新、身份与同步三条规则先正确,缓存优化才有意义。
核心模型
React 的一次渲染是输入快照到界面描述的纯计算,状态属于树中的身份,Effect 则让已经提交的界面与外部世界同步。更新、身份与同步三条规则先正确,缓存优化才有意义。
原理与机制
状态更新是队列而不是变量赋值
事件处理器闭包读取本次渲染的状态快照,setter 不会修改当前函数里的变量。连续 setN(n+1) 提交同一个替换值,函数式更新才把前一候选结果接着变换。批处理减少重复渲染工作,并不把三次替换自动变成三次累加。派生的 fullName 或过滤列表直接在渲染计算,避免通过 Effect 回填造成额外提交与中间不一致;写请求由明确事件触发,保存当次输入与操作身份。
身份决定状态跟着谁走
React 根据树中位置、组件类型与 key 关联状态。下标 key 在重排时可能让输入状态跟错记录,随机 key 则令实例持续重建。想切换对象时重置整份表单,可有意改变 key;跨卸载保存草稿则需按用户、租户和记录 ID 存在外层。组件定义放在父函数内会每次生成新类型,即使 key 不变也可能重置。useId 解决标签、输入与说明的 DOM 关联,不是数据主键;多根 SSR 要配套相同 identifierPrefix。
Effect 的每轮都需要资源归属
Effect 适合订阅、连接或参数驱动的外部同步,依赖反映实际读取的响应式值,不能靠删依赖压住重跑。每轮 setup 对应 cleanup,并使迟到成功、失败及 finally 都先检查本轮是否有效。AbortController 节约资源,但取消未必覆盖已排队回调。根 StrictMode 在开发期额外执行 setup、cleanup、setup,检验的是最终只有一份有效订阅;用 ref 跳过第二轮可能把已清理的资源永久跳过。
布局副作用处在绘制阻塞路径
useLayoutEffect 在 DOM 提交后、下一次绘制前执行,可先测量浮层再定位,避免用户看到错误位置;其中计算及状态更新会延迟绘制,因此仅承担必要的短工作。useEffect 通常适合连接等不需阻止画面呈现的同步,但不能说它永远在绘制后,交互触发时可能更早。两者都不在服务端执行,已经显示的 SSR 错位不能事后撤回;优先 CSS、稳定占位或客户端专属区域。
记忆化优化重复工作,不提供业务语义
memo 默认按 Object.is 比较 props,子组件自身状态与 Context 更新仍会渲染;新建函数和对象也会破坏引用稳定。useMemo 可缓存昂贵纯计算,useCallback 稳定有实际用途的函数身份,但都不能靠遗漏依赖维持旧闭包。React Compiler 自动记忆化同样依赖纯度和规则,需检查编译覆盖与诊断,渐进评估现有缓存。首次大计算、巨量 DOM 与错误生命周期不会因启用编译器自动消失,验收要看交互与提交成本。 迁移先留正确性与生产性能基线,小范围启用并验证外部库的引用身份约定,再决定是否删除已有缓存;代码变短不等于收益已经被证明。
Effect Event 分离同步条件与通知读取
聊天室连接由 roomId 决定时,roomId 是 Effect 的响应式依赖;通知主题仅在连接事件发生时取最新值,可以放入 useEffectEvent。不要把真正改变同步目标的输入藏进去,也不要把 Effect Event 传给其他组件/Hook 或当普通点击 handler。它不替代连接清理、迟到回调有效性判断或 useCallback 的用途。此能力按 React 19.2 起的语义教学,使用时仍需核对所用版本和相应 lint 支持。
自定义 Hook 复用逻辑,状态归属仍须明确
两个组件各调用 useCounter,内部 useState 仍各有实例,生命周期取决于对应的树身份。要共享同一计数,在共同 owner 调用一次并传递值/操作;Context 或外部 store 可以扩大读取范围,但共享来自那份状态的归属。两个订阅者同时响应 online/offline,只说明看到了同一外部事实,不能证明局部 React state 已合并。Hook 只封装边界,不能替错误依赖与缺失 cleanup 兜底。
Reducer 集中转换规则,并显式定义历史
当多条事件路径共享状态转换规则时,action 表达事件,纯 reducer 计算下一份不可变 state。dispatch 不改变当前 handler 的快照,reducer 不负责请求、写存储或生成不可控随机值。撤销必须先定义范围:只记录 count 前值,就只能撤销 count;要恢复 step 等字段,需要完整快照或明确的逆操作。useReducer 不自动获得全局共享、性能提升、持久化或完整事件日志。
最小示例
jsx在已导入 useState 的 React 组件中,初始点击日志为 0,提交后按钮显示 10:替换 5、变成 6、替换 9、变成 10。再次点击旧快照是 10,最后仍为 10。更新函数必须纯净,不能借它发送请求或累计外部计数,测试应断言提交后的 UI。
环境:React 19 客户端 JSX 项目;需从 react 导入 useState,再挂载 Counter;不是独立 Node.js 脚本。
核验:已静态审查示例与本章机制一致;未运行此示例,未进行框架或浏览器集成测试。观察结果为待复现的教学预期。
边界与取舍
边界
- key 是同级树身份,不要求全应用唯一;useId 不能代替业务列表 key。
- StrictMode 的额外检查是开发行为;根部未启用而仅局部启用时,初次 Effect 重跑规则也不同。
- memo 不是不渲染保证,useMemo 不是持久存储;useLayoutEffect 更早也不会让网络更快。
- 按产品身份决定 reset 与保留 · 业务 key 改变会重建子树,不是按 key 自动缓存已经卸载的草稿。跨实体切回仍需保留时,应把草稿放在能按实体标识保存的 owner;单字段清空无需重建整树。
- 模拟器不能证明 Compiler 生效 · 原站 React Compiler Demo 只演示心智模型;真实编译覆盖要看配置、诊断或产物,收益要在可比交互中量测。不得把该 Demo 的显示结果标为本项目的性能测试记录。
取舍
- 局部状态降低更新传播,但跨卸载草稿要提升归属;提升后须明确账号隔离和清理。
- 缓存与布局测量能改善特定体验,却增加比较、内存或绘制阻塞;先量测再使用。
- 自定义 Hook、reducer、Context 各解决复用、转换与传递问题;优先使用最小方案,避免为单个 boolean 引入一整套状态架构。
口述示范
我会用快照解释状态队列,用位置、类型和 key 解释状态身份,再把事件、纯派生值与外部同步分开。Effect 做对称清理并保护所有迟到写入;布局 Effect 只做必要测量。最后才以 Profiler 判断手工或编译器记忆化的收益。 复用逻辑时区分 Hook 调用与共享 owner;复杂事件转换可用纯 reducer 集中表达。Effect Event 只分离 Effect 内非响应式通知,不是删依赖的捷径;撤销与缓存都要明确各自的边界。
章节练习
可编辑列表删首项后草稿串行,同时父组件无关更新令输入丢焦,怎样定位?
展开检查点
- 检查稳定业务 key 与父函数内部组件定义。
- 区分切换对象重置和跨路由保留草稿。
- 验证重排、两份表单与 useId 标签关联。
- 比较两次 useCounter 调用与父组件一次调用后传值,明确共享 owner;说明切回记录保留草稿的存放位置。
参考来源与核验边界
- React:状态更新队列 · 核验 2026-10-04
- React:保留与重置状态 · 核验 2026-10-04
- React:useEffect · 核验 2026-10-04
- React:Compiler Introduction · 核验 2026-10-04
- 原创笔记:state-snapshot-queue · 核验 2026-10-04
正文与注册表已读取;关联实验未执行。
- 原创笔记:preserving-resetting-state · 核验 2026-10-04
正文与注册表已读取;关联实验未执行。
- 原创笔记:react-compiler · 核验 2026-10-04
正文与注册表已读取;关联实验未执行。
- 原创笔记:effect-event · 核验 2026-10-04
正文与注册表已读取;关联实验未执行。
- React 官方:effect-event · 核验 2026-10-04
- 原创笔记:custom-hooks · 核验 2026-10-04
正文与注册表已读取;关联实验未执行。
- React 官方:custom-hooks · 核验 2026-10-04
- 原创笔记:state-reducer · 核验 2026-10-04
正文与注册表已读取;关联实验未执行。
- React 官方:state-reducer · 核验 2026-10-04
按 React 19 系列和核验日官方文档;不假定项目已启用 React Compiler。StrictMode 的检查范围、编译器版本与构建覆盖需显式确认。 本次拟增补来源为 React Learning Playground 固定提交 49df03e3557f0b789aee77dbe23ca84d610cd166 的六个单元;Effect Event 以 React 19.2 起为最低版本条件。官方文档核对日为2026-10-04,在线参考可能随新版更新;本轮未运行新增教学示例、原站 Demo 或 Compiler 验证。
内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。