React useEffect 与 SSR

React 中 useEffect 为什么不会在服务端执行,以及它和首屏直出、客户端接管之间的关系。

#tech / dev / frame #resource / react #type / synthesis #status / growing

[!info] related notes

React useEffect 与 SSR

useEffect 一旦和 SSR 放在一起,最容易混乱的点是:页面明明已经在服务端渲出来了,为什么 effect 却没有在服务端执行。

一句话定义

useEffect 不会在服务端渲染阶段执行,因为它的职责是让组件在客户端和外部系统建立同步关系,而服务端渲染只负责产出 HTML,不负责浏览器里的副作用接管。

为什么它不会在服务端执行

  • 服务端渲染的目标是生成首屏 HTML
  • useEffect 依赖的是渲染提交后的客户端环境
  • 很多 effect 本来就和 DOM、事件、订阅、浏览器 API 有关
  • 这些东西在服务端并不存在或不应该执行

应该怎么理解 SSR 里的执行顺序

  • 服务端先根据组件树产出 HTML
  • 浏览器拿到 HTML 后先显示内容
  • 客户端 JavaScript 加载完成后开始 hydration
  • hydration 完成后,useEffect 才会在客户端参与同步外部系统

一个最重要的工程结论

不要把首屏必须的数据和内容寄托在 useEffect 上。

因为如果一段数据只能在 effect 里补:

  • 它就不会出现在服务端首屏 HTML 里
  • 用户可能先看到空壳或占位态
  • 这份能力本质上已经属于客户端补拉,而不是 SSR 直出

这也是为什么 SSR 里的首屏关键数据,通常要在服务端阶段准备。

这会带来什么影响

  • 不能指望 useEffect 参与服务端首屏数据直出
  • 首屏内容如果依赖 effect 才补齐,用户可能先看到不完整状态
  • 浏览器专属逻辑通常应该显式放在客户端阶段处理

一个典型场景

适合放在 useEffect 的 SSR 后置逻辑:

  • 埋点
  • 浏览器事件订阅
  • 客户端本地存储读取
  • 只在客户端出现的增强交互

常见误区

  • 以为“组件渲染了”就等于 effect 也执行了
  • 把首屏必须的数据准备放进 useEffect
  • 以为 SSR 能自动解决所有客户端副作用时机问题

最短记忆方式

SSR 负责先把页面画出来,useEffect 负责客户端接手后的外部同步。

面试要点

来自 react-use-effect-run-on-server-interview-question 的面试视角整理。

一句话回答

不会。useEffect 只会在客户端接管并完成渲染提交后执行,因为它本质上是在让组件和 DOM、事件、订阅、网络等外部系统同步,而服务端渲染只负责生成 HTML。

最稳的回答主线

  • SSR 阶段主要任务是产出 HTML
  • useEffect 属于客户端副作用同步机制
  • 页面先被服务端渲出来,不代表 effect 已经跑过
  • 真正等到浏览器加载脚本并开始 hydration 之后,effect 才会进入执行阶段

一个更完整的面试表达

可以这样答:

不会。useEffect 是客户端提交后的副作用同步机制,它要等浏览器端 React 接管页面后,才能去做 DOM、订阅、事件、网络同步这些事情。
服务端渲染阶段的职责只是根据组件树产出 HTML,不负责执行客户端副作用。

一个加分点

如果面试官继续问“那为什么这很重要”,可以补一句:

因为这意味着首屏关键数据不能指望 useEffect 去准备。只要某个数据必须等 effect 才补上,它本质上就不属于 SSR 直出的能力范围。

面试里容易加分的一句

如果首屏内容必须等 useEffect 里再去拿数据或补状态,那它天然就不是服务端首屏直出的那部分能力。

常见追问

  • 那 SSR 首屏数据一般怎么准备
  • useLayoutEffect 在服务端又是什么情况
  • 为什么页面已经显示了,某些逻辑还没生效

最短记忆方式

服务端只先渲页面,effect 等客户端接手后再跑。

创建于 2026/3/19 更新于 2026/5/27