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

React-router-dom 受保护路由失效及登录跳转异常求助

React路由保护问题:未登录可访问受保护页面+登录后无法跳转仪表盘

问题分析

你的代码存在两个核心问题:

  1. 路由渲染逻辑错误:非保护路由的渲染方式错误,给不需要to属性的组件(如Login、Register)强制传递了to参数,可能导致组件异常;同时受保护路由的权限判断依赖UserContext的状态,如果上下文状态未正确初始化或更新,会导致权限校验失效。
  2. 登录状态同步缺失:登录成功后未更新UserContext中的user状态,导致ProtectedRoute无法识别已登录状态,同时跳转逻辑可能未正确执行。

修复步骤

1. 修正路由渲染逻辑(index.js)

将非保护路由的渲染代码修改为区分Navigate组件和普通组件,避免错误传递to属性:

// 替换原routes.map中的非保护路由返回逻辑
if (route.protected) {
    return (
        <Route
            key={index}
            path={route.path}
            element={<ProtectedRoute element={route.element} />}
        />
    );
}
// 区分Navigate和其他组件
if (route.element === Navigate) {
    return (
        <Route
            key={index}
            path={route.path}
            element={<Navigate to={route.to} />}
        />
    );
} else {
    return (
        <Route
            key={index}
            path={route.path}
            element={<route.element />}
        />
    );
}

2. 确保UserContext状态正确管理

检查你的userContext.js,确保初始状态和登录状态更新逻辑正确:

import { createContext, useState, useEffect } from 'react';
import axios from 'axios';

export const UserContext = createContext();

export const UserContextProvider = ({ children }) => {
    const [user, setUser] = useState(null);
    const [loading, setLoading] = useState(true);

    // 初始化时检查用户登录状态
    useEffect(() => {
        const checkAuthStatus = async () => {
            try {
                const response = await axios.get('/api/auth/check');
                setUser(response.data.user);
            } catch (error) {
                setUser(null);
            } finally {
                setLoading(false);
            }
        };
        checkAuthStatus();
    }, []);

    // 登录成功后更新用户状态
    const loginUser = (userData) => {
        setUser(userData);
    };

    // 登出时清除用户状态
    const logoutUser = () => {
        setUser(null);
    };

    return (
        <UserContext.Provider value={{ user, loading, loginUser, logoutUser }}>
            {children}
        </UserContext.Provider>
    );
};

3. 完善登录页的状态更新与跳转逻辑

在Login组件中,登录成功后调用loginUser更新上下文状态,并执行跳转:

import { useState, useContext } from 'react';
import { useNavigate } from 'react-router-dom';
import { UserContext } from '../../context/userContext';
import axios from 'axios';

const Login = () => {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const { loginUser } = useContext(UserContext);
    const navigate = useNavigate();

    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            const res = await axios.post('/api/auth/login', { email, password });
            // 更新上下文用户状态
            loginUser(res.data.user);
            // 跳转到仪表盘
            navigate('/dashboard');
        } catch (err) {
            console.error('登录失败:', err);
            // 这里可以添加错误提示逻辑
        }
    };

    return (
        <form onSubmit={handleSubmit} className="login-form">
            <input
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder="邮箱"
                required
            />
            <input
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                placeholder="密码"
                required
            />
            <button type="submit">登录</button>
        </form>
    );
};

export default Login;

4. 验证ProtectedRoute逻辑

确保ProtectedRoute的权限判断逻辑正确,当loading为true时显示加载状态,未登录时重定向到登录页:

import React, { useContext } from 'react';
import { Navigate } from 'react-router-dom';
import { UserContext } from '../context/userContext';
import { Loader } from 'lucide-react';

const ProtectedRoute = ({ element: Component }) => {
    const { user, loading } = useContext(UserContext);

    if (loading) {
        return (
            <div className='flex items-center justify-center py-4'>
                <Loader className='animate-spin mr-2' />
                <span>加载中...</span>
            </div>
        );
    }

    // 未登录则重定向到登录页
    return user ? <Component /> : <Navigate to='/login' replace />;
};

export default ProtectedRoute;

关键注意点

  • 确保后端接口/api/auth/check能正确返回当前登录用户信息,且axios.defaults.withCredentials = true已配置,保证cookie传递正常。
  • 登录接口返回的用户数据需包含有效标识(如id、用户名等),确保user状态不为null。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:25:24