React useEffect 与 SSR
React 中 useEffect 为什么不会在服务端执行,以及它和首屏直出、客户端接管之间的关系。
[!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 等客户端接手后再跑。