为什么React组件挂载前的状态变更触发函数执行但未在页面渲染?
核心原因
这个现象是React开发环境下严格模式的双调用机制导致的,和useState的更新逻辑本身无关。
React的<React.StrictMode>包裹组件时,开发环境下会故意在组件首次挂载的渲染阶段,连续调用两次组件函数,用来检测代码中是否存在不安全的副作用(比如你用的全局可变变量isFirstRender就属于这类)。
你的代码具体执行流程如下:
- 第一次调用
App组件:- 全局变量
isFirstRender初始为true,进入if分支 - 调用
setValue("two"),当前渲染周期的状态更新为two - 全局变量
isFirstRender被设为false - 控制台打印
-- render -- {value: "two"} - 本次返回的JSX里
Value显示为two
- 全局变量
- 严格模式触发第二次无副作用的组件调用(这一步不会触发useEffect等钩子,仅纯调用组件函数):
- 全局变量
isFirstRender已经是false,不会进入if分支 useState取初始值"one",所以value为one- 控制台打印
-- render -- {value: "one"} - 本次返回的JSX里
Value显示为one
- 全局变量
- React最终会把第二次调用得到的JSX提交挂载到页面,所以你看到页面显示
one。
你可以尝试去掉外层的<React.StrictMode>包裹,页面就会正常显示two。
问题解答
useState的setter函数触发组件函数调用,不就意味着组件会使用更新后的状态值完成渲染吗?
setter触发的更新一定会被处理,但你的场景里不是setter没生效,而是严格模式的第二次组件调用覆盖了第一次的更新结果。另外需要注意:在组件渲染阶段(也就是组件函数执行过程中)同步调用setter,React会把更新合并到当前渲染批次,不会触发额外的重渲染。我原本认为在React中函数组件被调用就等同于触发一次渲染,组件挂载前的阶段是这个规则的例外吗?
组件函数被调用只是渲染阶段的计算步骤,不等于最终会提交到DOM。React的渲染流程分为「渲染阶段(计算JSX)」和「提交阶段(更新DOM)」,严格模式的双调用只发生在渲染阶段,只有最终提交的那次计算结果才会显示到页面上,并不是规则例外。
另外补充建议:不要在组件顶层写修改全局状态、调用setter这类副作用逻辑,组件顶层应该保持纯函数的特性,副作用逻辑统一放到useEffect中处理。
内容的提问来源于stack exchange,提问作者Andru
相关产品推荐
相关产品推荐

