Hydration failed because the initial UI does not match what was rendered on the

1,602 阅读1分钟

Next 项目,报错:

Unhandled Runtime Error

Error: Hydration failed because the initial UI does not match what was rendered on the server. See more info here: nextjs.org/docs/messag…

控制台还有报错,根据不同组件渲染有不同报错:

其中都有这个报错:

Error: Hydration failed because the initial UI does not match what was rendered on the server.

  1. 一个似乎是 antd 的报错:

Warning: Prop style did not match. Server: "width:200px" Client: "width:180px"

  1. 一个是:

Warning: Expected server HTML to contain a matching <div> in <div>.

梳理一下需求:

页面上有 6 个按钮,根据一个变量控制显示对应的 6 个组件。变量保存本地存储。

表现:

  • 初始:没有报错,点击按钮切换组件也无报错。
  • 如果点击按钮变量改变,刷新页面,因为本地存储的变量已变,页面加载的组件与初始不同,报错。

Next 报错:

2f885a3744316063822df62c58a42a6.png

搜索了一番,最后还是回到保存本身提供的链接:nextjs.org/docs/messag… 主要意思是,Next 服务端渲染内容和客户端初次渲染不匹配。

查看页面源代码:

确实与浏览器渲染代码不一致

解决办法: 避免服务端渲染和客户端渲染不一致,使用 useEffect 的客户端中进行对应的修改。

初始代码:

const [dataSetCode, setDataSetCode] = useLocalStorageState<
  string | undefined
>('dataSetCode', {
  defaultValue: 'staff',
})

使用 ahooks 的 useLocalStorageState 定义变量 dataSetCode,进行本地存储。

但是如果本地存储已经不是初始默认值,就会导致上面渲染不匹配的问题。

修改代码:

const [dataSetCode, setDataSetCode] = useState<string | undefined>('')
  const [code, setCode] = useLocalStorageState<string | undefined>(
    'dataSetCode',
    {
      defaultValue: 'staff',
    },
  )
  
  useEffect(() => {
    setDataSetCode(code)
  }, [code])

参考: