Next.js AuthGuard组件首次加载Local Storage未读取,刷新后恢复正常
解决Next.js AuthGuard首次加载无法读取LocalStorage导致的路由跳转问题
你的问题核心在于Next.js的服务端渲染特性:首次页面渲染是在服务端完成的,此时window对象不存在,直接调用window.localStorage.getItem('userData')会取不到值,再加上auth.user===null的判断,组件会直接返回fallback加载器。只有当页面完成客户端hydration后刷新,客户端环境下才能正常读取LocalStorage,触发路由跳转逻辑。
修改方案
下面是调整后的代码,同时附上关键修改说明:
import { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; const AuthGuard = props => { const { children, fallback } = props; const auth = useAuth(); const router = useRouter(); // 标记当前是否处于客户端环境 const [isClient, setIsClient] = useState(false); useEffect(() => { // 组件挂载后才切换为客户端环境状态 setIsClient(true); }, []); useEffect(() => { // 路由未就绪或非客户端环境时不执行逻辑 if (!router.isReady || !isClient) return; // 仅在客户端读取LocalStorage const hasUserData = window.localStorage.getItem('userData'); if (auth.user === null && !hasUserData) { const returnUrlConfig = router.asPath !== '/' ? { query: { returnUrl: router.asPath } } : {}; router.replace({ pathname: '/login', ...returnUrlConfig }); } }, [router.isReady, auth.user, isClient, router.asPath]); // 服务端阶段或auth仍在加载时,返回fallback if (!isClient || auth.loading) { return fallback; } // 客户端环境下,用户未登录时返回null(路由跳转后会自动切换页面) if (auth.user === null) { return null; } return <>{children}</>; }; export default AuthGuard;
关键修改点说明
- 新增
isClient状态:确保只有在客户端环境下才执行LocalStorage读取和路由跳转,避免服务端因window不存在报错 - 优化
useEffect依赖:加入router.isReady、auth.user和router.asPath,保证路由就绪、用户状态变化或路径改变时,都能触发登录判断逻辑 - 调整渲染条件:服务端阶段或auth加载中才返回fallback;客户端环境下用户未登录时返回
null,配合路由跳转完成页面切换,不会一直显示加载器
内容的提问来源于stack exchange,提问作者Yogesh Singh
相关产品推荐
相关产品推荐

