关于 React 的报错 Hydration failed 解决办法

2,021 阅读2分钟

最近在学习react,和next配合使用。在使用过程中遇见了 Error: Hydration failed because the initial UI does not match what was rendered on the server. 这个错误,大概情况是 服务端不渲染这个组件的,是到客户端才渲染这个组件。

若是使用同一份代码,在服务器端和客户端都进行渲染,则不会出现这个奇怪的问题。

在网上查了资料后发现,大概可能是如下几种情况之一:

  1. 数据加载方式不一致:可能会导致在客户端渲染时,使用了不同的数据源或者加载方式,导致了渲染结果不一致。解决方法是在客户端和服务器端使用相同的数据源或者加载方式。
  2. 渲染方式不一致:可能会导致在客户端渲染时,使用了不同的渲染方式或者库,导致了渲染结果不一致。解决方法是在客户端和服务器端使用相同的渲染方式或者库。
  3. 组件或模板不一致:可能会导致在客户端渲染时,使用了不同的组件或模板,导致了渲染结果不一致。解决方法是在客户端和服务器端使用相同的组件或模板。
  4. 数据格式不一致:可能会导致在客户端渲染时,使用了不同的数据格式,导致了渲染结果不一致。解决方法是在客户端和服务器端使用相同的数据格式。

我采用的解决办法是将渲染页面直接粗暴的丢到了 页面加载之后。 因为存在一个问题,我所遇见的情况,是 MarkDownView 这个我自己封装的组件并不支持在服务端渲染,必须在客户端渲染。而服务端渲染和客户端渲染的结果又不一样。结果就导致了 水合失败。

const Discuss = (props) => {
  const [rendernode, setRendernode] = useState(<></>)
  const node = <MarkdownView text={blog.content} />;
  useEffect(() => {
    setRendernode(node)
  }, []);

  return <div>
    <div className={cssStyle.content}>
      <div className={cssStyle.info}>
        {rendernode}
      </div>
    </div>
  </div>
}

这个错误通常是在使用服务端渲染(SSR)时出现的,它的原因是 React 在服务端渲染完成后生成的 HTML 和客户端渲染时生成的 HTML 不一致导致的。

在 React 服务端渲染中,React 会将组件渲染成 HTML 字符串,然后发送到客户端。在客户端,React 会重新创建组件并将其挂载到 DOM 上。如果服务端渲染时生成的 HTML 和客户端渲染时生成的 HTML 不一致,就会出现“hydration failed”(水合失败)的错误。