## 防止水合不匹配导致的闪烁
当渲染依赖于客户端存储(localStorage、cookies)的内容时,通过注入一个在 React 水合之前同步更新 DOM 的脚本,可以避免 SSR 崩溃和水合后的闪烁。
**错误做法(导致 SSR 崩溃):**
tsx
function ThemeWrapper({ children }: { children: ReactNode }) {
// localStorage 在服务端不可用 - 会抛出错误
const theme = localStorage.getItem('theme') || 'light'
return (
{children}
)
}
服务端渲染会失败,因为 `localStorage` 未定义。
**错误做法(视觉闪烁):**
tsx
function ThemeWrapper({ children }: { children: ReactNode }) {
const [theme, setTheme] = useState('light')
useEffect(() => {
// 在水合后运行 - 导致可见的闪烁
const stored = localStorage.getItem('theme')
if (stored) {
setTheme(stored)
}
}, [])
return (
{children}
)
}
组件首先使用默认值(`light`)渲染,然后在水合后更新,导致内容出现明显的闪烁。
**正确做法(无闪烁,无水合不匹配):**
tsx
function ThemeWrapper({ children }: { children: ReactNode }) {
return (
{children}
)
}
内联脚本在显示元素之前同步执行,确保 DOM 已经拥有正确的值。没有闪烁,也没有水合不匹配。
这种模式特别适用于主题切换、用户偏好设置、认证状态以及任何需要在不闪烁默认值的情况下立即渲染的客户端数据。