标准答案

  1. Hydration 要求客户端首次渲染结果尽量和服务端 HTML 一致,否则会出现警告或重新渲染。
  2. Date.now、Math.random、Intl 时区差异、浏览器宽度判断都可能让服务端和客户端输出不同内容。
  3. 直接在渲染阶段读取 window、localStorage、matchMedia 等浏览器 API,容易造成环境差异。
  4. 服务端和客户端请求到的数据版本不同,也会导致文本、列表或属性不一致。
  5. 修复思路是让首屏输出稳定,把客户端专属逻辑放进 effect,或用明确的客户端组件边界。

题目解析

这道题的核心是“首屏一致性”。服务端 HTML 已经存在,客户端接管时不能生成另一份完全不同的树。

有些差异看起来只是文本不同,但在复杂树里可能造成事件绑定、DOM 结构和状态接管问题。

定位时要先找不确定输入:时间、随机、环境变量、浏览器 API、异步数据和条件分支。

代码示例

下面把浏览器宽度判断放到 effect 后执行,避免服务端首屏和客户端首屏不一致。

TSX
function ResponsiveLabel() {
  const [isMobile, setIsMobile] = useState(false)

  useEffect(() => {
    setIsMobile(window.matchMedia('(max-width: 768px)').matches)
  }, [])

  return <span>{isMobile ? '移动端' : '桌面端'}</span>
}

常见误区

  • 在服务端渲染路径里直接读取 window 或 localStorage。
  • 首屏渲染中使用随机数和当前时间,却没有保证服务端和客户端一致。
  • 忽略非法 HTML 嵌套,导致浏览器修正 DOM 后和 React 期望结构不同。

作者信息