标准答案
- Hydration 要求客户端首次渲染结果尽量和服务端 HTML 一致,否则会出现警告或重新渲染。
- Date.now、Math.random、Intl 时区差异、浏览器宽度判断都可能让服务端和客户端输出不同内容。
- 直接在渲染阶段读取 window、localStorage、matchMedia 等浏览器 API,容易造成环境差异。
- 服务端和客户端请求到的数据版本不同,也会导致文本、列表或属性不一致。
- 修复思路是让首屏输出稳定,把客户端专属逻辑放进 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 期望结构不同。