438 字
2 分钟
Next.js 在 Safari 浏览器中异常的水合错误
问题描述
我在使用 Next.js(v15.1.7
) 开发时,使用 HeroUI 组件库的 ListBox 组件时,遇到了水合错误。
一开始在 Chromium 内核的浏览器中一切正常,但是当我在开发者工具中切换到移动端(iphone系列)时,发现组件使用正常但是控制台报水合错误,我一开始的第一反应是移动端代码有问题,经过排查发现并不是,而是 Next.js 在 Safari 浏览器中对于标签嵌套的渲染有问题。
问题排查
经过排查,发现问题出在 ListBox 和 ListItem 的标签渲染上,ListBox 默认渲染为 ul 标签,ListItem 默认渲染为 li 标签,虽然这一切看着正常,但是可能是 Next.js 在 Safari 浏览器中对于组件的渲染有问题,导致水合错误。
伪代码如下:
// Sidebar.tsx
import { Listbox, ListboxItem } from "@heroui/react";
export default function Sidebar() {
return (
<Listbox as="ul">
<ListboxItem as="li" />
</Listbox>
)
}
解决方案
按照如下组合尝试修改:
- ListBox -> ul && ListboxItem -> li
- ListBox -> ol && ListboxItem -> li
- ListBox -> div && ListboxItem -> div
- ListBox -> div && ListboxItem -> p
- ListBox -> p && ListboxItem -> p
对于 chromium 内核的浏览器只有使用 p 标签嵌套 p 标签才会出现水合错误,其他标签组合则不会出现水合错误。
而对于 Safari 浏览器,则所有标签组合都会出现水合错误。
因此,可见 Next.js 在 Safari 浏览器中对于组件的渲染有问题,为了解决这个问题(在应对水合错误时,官方推荐的解决方案之一),可以使用 dynamic
组件来动态渲染组件,跳过 Next.js 的预渲染。
// Layout.tsx
import dynamic from "next/dynamic";
const Sidebar = dynamic(() => import("@/components/Sidebar"), { ssr: false });
Next.js 在 Safari 浏览器中异常的水合错误
https://www.mihouo.com/posts/front/nextjs-hydration-error-in-safari-browser/