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

React实现条件触发自动页面跳转(路由鉴权场景)问题求助

可行实现方案

核心问题说明

你用的是React Router v6版本,之前跳转不生效有四个直接原因:

  • 旧版的Redirect组件在v6中已经被移除,不能再使用
  • 声明式跳转组件Navigate必须放在组件return的渲染分支里才会生效,写在普通逻辑、事件回调里不会触发渲染,自然没有效果
  • 事件回调里的跳转要使用v6提供的useNavigate命令式API,只存储cookie不会触发路由切换
  • 混用原生document.cookie和引入的js-cookie库操作cookie,两者默认路径配置不一致,很容易出现存完cookie之后读不到值的问题

具体实现步骤

1. 实现未携带token访问首页自动跳转登录页

直接修改Home组件,引入Navigate组件,在组件渲染阶段判断token是否存在,不存在则直接返回重定向组件。
修改后的Home组件代码:

import React from 'react';
import '../styles/home.css'
import { Navigate } from 'react-router-dom'
import cookie from 'js-cookie'

const Home = () => {
    const token = cookie.get('token')
    const userId = cookie.get('userId')

    // 无合法token直接重定向到登录页,replace替换历史记录避免回退死循环
    if (!token || !userId) {
        return <Navigate to="/login" replace />
    }

    return (
        <>
            Home
        </>
    );
}

export default Home;

2. 实现注册/登录成功后自动跳转首页

在Login、Register组件中引入useNavigate hook拿到跳转方法,接口请求成功、cookie存储完成后,调用跳转方法切到首页,同时统一用js-cookie的set方法存储cookie,和读取逻辑保持一致避免异常。
修改后的Register组件代码:

import React, {useState} from 'react';
import '../styles/register.css'
import axios from 'axios'
import { useNavigate } from 'react-router-dom'
import cookie from 'js-cookie'

const Register = () => {
    const [name, setName] = useState('')
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const navigate = useNavigate()

    const registerUser = (e) => {
        e.preventDefault()
        axios.post('/api/user/register', {
            name: name,
            email: email,
            password: password
        }).then(res => {
            cookie.set('token', res.data.token)
            cookie.set('userId', res.data.userId)
            // 注册成功跳转首页,replace替换当前历史记录,避免用户点回退回到注册页
            navigate('/', { replace: true })
        }).catch(err => {
            alert(`Error registering!`)
            setName('')
            setEmail('')
            setPassword('')
            console.log(err)
        })
    }

    return (
        <>
            <form onSubmit={e => registerUser(e)}>
                <input type="text" placeholder="Enter your Name" value={name} onChange={e => setName(e.target.value)}/>
                <br/>
                <input type="email" placeholder="Enter your Email" required={true} value={email}
                       onChange={e => setEmail(e.target.value)}/>
                <br/>
                <input type="password" placeholder="Enter your Password" required={true} value={password}
                       onChange={e => setPassword(e.target.value)}/>
                <br/>
                <button type="submit">Register</button>
            </form>
        </>
    );
}

export default Register;

修改后的Login组件逻辑和Register完全一致,替换对应接口地址、提示文案即可:

import React, {useState} from 'react';
import '../styles/register.css'
import axios from 'axios'
import { useNavigate } from 'react-router-dom'
import cookie from 'js-cookie'

const Login = () => {
    const [name, setName] = useState('')
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const navigate = useNavigate()

    const loginUser = (e) => {
        e.preventDefault()
        axios.post('/api/user/login', {
            name: name,
            email: email,
            password: password
        }).then(res => {
            cookie.set('token', res.data.token)
            cookie.set('userId', res.data.userId)
            navigate('/', { replace: true })
        }).catch(err => {
            alert(`Error logging in!`)
            setName('')
            setEmail('')
            setPassword('')
            console.log(err)
        })
    }

    return (
        <>
            <form onSubmit={e => loginUser(e)}>
                <input type="text" placeholder="Enter your Name" value={name} onChange={e => setName(e.target.value)}/>
                <br/>
                <input type="email" placeholder="Enter your Email" required={true} value={email}
                       onChange={e => setEmail(e.target.value)}/>
                <br/>
                <input type="password" placeholder="Enter your Password" required={true} value={password}
                       onChange={e => setPassword(e.target.value)}/>
                <br/>
                <button type="submit">Login</button>
            </form>
        </>
    );
}

export default Login;

补充优化(可选)

如果后续路由增多,可以把鉴权逻辑抽成公共的ProtectedRoute组件,不用每个需要鉴权的页面都重复写token判断:

// 组件位置:./components/ProtectedRoute.jsx
import { Navigate } from 'react-router-dom'
import cookie from 'js-cookie'

const ProtectedRoute = ({ children }) => {
    const token = cookie.get('token')
    if (!token) {
        return <Navigate to="/login" replace />
    }
    return children
}

export default ProtectedRoute

抽完之后入口文件的路由可以改成下面的写法,后续新增受保护路由直接套这个组件即可:

// 修改Index.jsx中的Routes部分
<Routes>
    <Route path='/' element={
        <ProtectedRoute>
            <Home />
        </ProtectedRoute>
    } />
    <Route path='/login' element={<Login/>}/>
    <Route path='/register' element={<Register/>}/>
</Routes>

抽离后Home组件里就不用再单独写token判断逻辑,维护成本更低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:54:27