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

Next.js 12中使用含useState的Hook出现SSR Hydration错误原因咨询

为什么含useState的自定义Hook会导致SSR Hydration不匹配?

场景说明

App和path由ctx中的URL确定,通过getServerSideProps作为props传递给组件。

出现Hydration错误的自定义Hook代码

// Hook
export default function usePath(app, path) {
  const [currentPath, setCurrentPath] = useState('')

  useEffect(() => {
    const config = globalConfig[app]

    if (config) {
      const { paths } = globalConfig

      const isMatching = paths.find(({ pattern }) => pattern.test(path))

      if (isMatching) {
        setCurrentPath(isMatching.path)
      }
    }
  }, [app, path])

  return currentPath
}

组件使用该Hook的代码

const currentPath = usePath(app, path)

// Hydration error here:
<p>{app && currentPath ? t(`sentence.${currentPath}`) : t(`sentence.defaultMessage`)}</p>

/* 
Server renders: sentence.defaultMessage, 
while the client renders: sentence.${currentPath}. 
*/

可正常运行的Hook代码(移除useState和useEffect)

export default function useChainPath(app, path) {
  const config = globalConfig[app]
  let currentPath = ''


  if (config) {
    const { paths } = config

    const isMatching = paths.find(({ pattern }) => pattern.test(path))

    if (isMatching) {
      currentPath = isMatching.path
    }
  }

  return currentPath
}

底层原因解析

Hydration不匹配的核心是服务端渲染的DOM结构与客户端首次渲染的DOM结构不一致,具体到这个场景:

  1. 服务端渲染阶段:

    • 服务端执行组件代码时,useState初始化currentPath为''
    • React的副作用钩子(比如useEffect)在服务端完全不执行
    • 最终服务端渲染出的是t('sentence.defaultMessage')对应的内容
  2. 客户端Hydration阶段:

    • 客户端首次渲染时,useState同样初始化currentPath为'',此时渲染内容和服务端一致,Hydration初期无问题
    • 但Hydration完成后,React会立即执行useEffect钩子:根据app和path匹配到目标currentPath,调用setCurrentPath更新状态
    • 状态更新触发组件重新渲染,此时渲染出t(sentence.${currentPath})的内容,和服务端最初输出的DOM产生差异,触发Hydration错误
  3. 对比修复后的Hook:

    • 修复后的Hook直接在函数体内同步计算currentPath,服务端和客户端执行时会得到完全相同的结果
    • 没有依赖副作用钩子延迟更新状态,服务端和客户端首次渲染的内容完全一致,不会触发不匹配问题

本质上,你把本该同步计算的逻辑放到了客户端副作用里,导致服务端与客户端的首次渲染结果产生偏差,而Hydration要求两者输出的DOM必须严格一致。

内容的提问来源于stack exchange,提问作者octavemirbeau

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 16:12:54