You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js随机数渲染触发Hydration水合报错如何解决

报错根因

Next.js 采用服务端渲染+客户端水合的渲染流程:服务端会先执行组件代码生成静态HTML发送到浏览器,之后浏览器会加载JS bundle,在客户端重新执行一遍组件逻辑,和已有的HTML做匹配完成交互绑定,这个匹配过程要求两端首次渲染的输出完全一致。
你的代码在组件首次渲染时直接调用了基于Math.random()的随机数生成逻辑:服务端渲染时会生成第一组随机数写入HTML,客户端水合时Math.random()会生成完全不同的第二组随机数,两端渲染出的文本内容不匹配,直接触发水合失败报错。
另外你的组件名teste是小写开头,不符合React组件必须大写开头的命名规范,也可能引发额外的渲染异常。

可行修复方案

方案1:将随机生成逻辑移到客户端挂载后执行

使用useEffect包裹随机数生成逻辑,useEffect只会在客户端水合完成后执行,不会参与服务端首次渲染,从根源避免两端结果不一致的问题。
如果你使用App Router,需要在文件顶部加'use client'标记为客户端组件;Pages Router无需加这行。
修改后的页面组件代码:

'use client'
import { useState, useEffect } from 'react'
import numeros from "../../functions/numberGenerators.js"

export default function Teste() {
  const [numberList, setNumberList] = useState([])

  useEffect(() => {
    setNumberList(numeros())
  }, [])

  return numberList.map(n =>  
    <div key={n}>
      Number: {n}
    </div>
  )
}

你原来的随机数工具函数不需要做任何修改。

方案2:关闭对应组件的服务端渲染

如果组件不需要SEO、不需要首屏直出,可以直接用Next.js提供的动态导入能力关闭组件的SSR,让组件只在客户端渲染:

// 页面文件
import dynamic from 'next/dynamic'
const Teste = dynamic(() => import('../../components/Teste'), { ssr: false })

export default function Page() {
  return <Teste />
}

方案3:保留SSR能力,在服务端数据获取阶段生成随机数

如果需要首屏就展示随机数内容、保留SSR的SEO和加载速度优势,可以把随机数生成逻辑放到服务端数据获取方法中执行,生成的结果作为props传递给页面组件,这样服务端生成的随机数会随HTML一起传递到客户端,两端内容完全一致不会触发水合错误。
以Pages Router的getServerSideProps为例:

import numeros from "../../functions/numberGenerators.js"

export async function getServerSideProps() {
  const numberList = numeros()
  return { props: { numberList } }
}

export default function Teste({ numberList }) {
  return numberList.map(n =>  
    <div key={n}>
      Number: {n}
    </div>
  )
}
水合报错通用排查思路
  • 检查组件首次渲染逻辑中是否存在执行结果不确定的代码:比如Math.random()、Date.now()这类每次调用返回值不同的方法,这类逻辑不要直接放在组件函数顶层执行,可以放到useEffect、事件回调或者服务端数据获取阶段。
  • 检查是否在组件首次渲染时直接访问仅客户端存在的API:比如window、document、localStorage等对象,这类对象在服务端不存在,直接访问要么报引用错误,要么因为兜底值不同导致渲染结果不一致。
  • 检查HTML标签嵌套是否符合规范:比如<p>标签嵌套<div>、<a>标签嵌套其他可点击元素这类写法,浏览器会自动修正不合法的DOM结构,导致水合时客户端DOM和服务端输出的DOM结构不匹配。
  • 排除浏览器扩展干扰:部分广告拦截、页面翻译、脚本注入类扩展会自动修改页面DOM结构,也会触发水合报错,可以打开无痕模式禁用所有扩展后复现测试。

内容的提问来源于stack exchange,提问作者Gabriel-vieira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:30:47