Next.js 13 中如何修复认证组件的 Hydration 错误?
修复 Next.js 13 Hydration 失败问题
错误原因
你的认证组件在服务器端渲染时返回 null,但客户端首次 hydration 时会立刻检查 localStorage,可能直接渲染目标组件或跳转路由,导致服务器与客户端初始渲染的 UI 不一致,触发 Hydration 不匹配错误。
修复方案
修改高阶组件,用 useEffect 延迟认证逻辑(useEffect 仅在客户端执行),同时通过状态同步服务器与客户端的初始渲染结果:
import { useRouter } from "next/router"; import { useState, useEffect } from "react"; const withAuth = (WrappedComponent: any) => { return (props: any) => { const router = useRouter(); // 初始状态为 null,保证服务器和客户端初始渲染一致 const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null); useEffect(() => { // 仅在客户端执行认证检查 const accessToken = localStorage.getItem("token"); if (!accessToken) { router.replace("/authentication/login"); } else { setIsAuthenticated(true); } }, [router]); // 初始渲染返回 null(或加载组件),避免 Hydration 不匹配 if (isAuthenticated === null) { return null; // 可选:替换为加载组件提升体验 // return <div>加载中...</div> } // 认证通过后渲染目标组件 return isAuthenticated ? <WrappedComponent {...props} /> : null; }; }; export default withAuth;
关键改动说明
- 状态同步:用
isAuthenticated状态控制渲染,初始值null让服务器和客户端首次渲染均返回相同内容(null)。 - 延迟认证:
useEffect只在客户端 hydration 完成后执行,此时再检查localStorage并处理路由或更新状态,不会破坏 Hydration 过程。 - 避免顶层操作:不在组件顶层直接访问
localStorage或执行路由跳转,这类操作仅在客户端有效,会导致服务器与客户端渲染结果不一致。
内容的提问来源于stack exchange,提问作者Arash Barghash
相关产品推荐
相关产品推荐

