You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS13中Auth Context下已登录访问受保护页面仍跳转首页问题

已登录状态下访问受保护Profile页面先显示内容再跳转首页的问题排查与修复

问题根源分析

  1. AuthContext初始状态错误:statusAuth初始值设为'unauthenticated',导致页面初始渲染时,Profile组件直接跳过loading分支,先渲染用户信息;同时useEffect检测到初始状态满足跳转条件,触发首页跳转。后续checkIsLoggedin请求完成后状态更新为'authenticated',但跳转已发起,因此出现先显示内容再跳转的异常。
  2. Token存储/解析不一致:存储token时使用JSON.stringify,但取出时未解析,导致token包含多余引号,getMe请求的Authorization头无效,服务器返回401,间接触发跳转逻辑。

修复方案

1. 修正AuthContext初始状态

将statusAuth初始值改为'loading',确保认证状态未确定前显示loading,避免错误渲染和跳转:

const [user, setUser] = useState<IUser | null>(null)
// 初始状态设为loading,而非unauthenticated
const [statusAuth, setStatusAuth] = useState('loading')

const checkIsLoggedin = async () => {
    try {
        const data = await AxiosGlobal.get('/auth/getMe')
        if (data.status === 200) {
            setUser(data.data.user)
            setStatusAuth('authenticated')
        } else {
            setUser(null)
            setStatusAuth('unauthenticated')
        }
    } catch (error) {
        setUser(null)
        setStatusAuth('unauthenticated')
    }
}
useEffect(() => {
    checkIsLoggedin()
}, [])

return (
    <AuthContext.Provider
        value={{
            user,
            setUser,
            statusAuth,
            setStatusAuth,
        }}
    >
        {children}
    </AuthContext.Provider>
)

2. 优化Profile组件跳转逻辑

简化useEffect判断条件,仅基于statusAuth做跳转决策:

'use client'
import { useContext, useEffect } from "react"
import { AuthContext } from "@/contexts/AuthContext"
import { useRouter } from 'next/navigation'

const Profile = () => {
    const router = useRouter()
    const { user, statusAuth } = useContext(AuthContext)

    useEffect(() => {
        // 仅当认证状态为unauthenticated时跳转
        if(statusAuth === 'unauthenticated') {
            router.push('/')
        }
    }, [router, statusAuth])

    if (statusAuth === 'loading') return <>loading.........</>

    return (
        <div>Profile user is here {user?.email}</div>
    )
}

export default Profile

3. 修复Token存储/解析问题

统一token的存储和解析逻辑,避免Authorization头无效:

// Axios请求拦截器修改token获取逻辑
AxiosGlobal.interceptors.request.use(async (config) => {
    if(config.url === '/auth/refresh-token' && config.method === 'post') {
        return config
    }
    // 解析localStorage中的token,去除多余引号
    const tokenStr = localStorage.getItem('accessToken');
    const token = tokenStr ? JSON.parse(tokenStr) : null;

    if(token) {
        config.headers.Authorization = `Bearer ${token}`
    }

    return config
}, (error) => {
    return Promise.reject(error)
})

// 同时修改refresh-token成功后的存储逻辑(若token本身是字符串,无需JSON.stringify)
// 替换原来的存储代码
localStorage.setItem('accessToken', data.token)

内容的提问来源于stack exchange,提问作者Minh Huy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 12:45:58