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

React应用中Logout后useNavigate无法跳转至根页面问题

React应用登出后无法跳转至根页面问题

问题描述

开发基础React应用时,Navbar组件的Logout按钮点击后,虽能执行处理函数并清除AuthContext,但无法跳转到根页面(/),停留在当前URL。使用navigate(-1)可返回上一页,但无法满足后续多页面场景下跳转到根页面的需求,怀疑问题出在路由配置或按钮事件处理上。

相关代码

const Navbar = () => {
  const { setAuth } = useContext(AuthContext)
  const navigate = useNavigate();

  const handleLogout = (e) => {
    setAuth(null)
    navigate("/");
    console.log("logout has been clicked");
  }

  return (
    <nav>
      <input type="checkbox" id="check" />
      <label for="check" className="checkbtn">
        <i className="fas fa-bars">Quz</i>
      </label>
      <label className="logo">Create Your Best Team</label>
      <ul>
        <li><Link to="">Messages</Link></li>
        <li><Link to="/student" className="active">Profile</Link></li>
        <li><Link to="">My Group</Link></li>
        <li><Link onClick={handleLogout}>Logout</Link></li>
      </ul>
    </nav>
  )
}

export default Navbar;

InnerApp组件

import Login from './components/Login'
import Student from './components/Student';
import Teacher from './components/Teacher'
import Navbar from './components/Navbar/Navbar';
import { MantineProvider } from '@mantine/core';
import { Routes, Route } from 'react-router-dom';
import { useContext } from "react"
import RequireAuth from './customHooks/RequireAuth';
import AuthContext from "./context/AuthProvider";

function InnerApp() {
  const { auth } = useContext(AuthContext)
  return (
    <MantineProvider>
      {auth?.name ? <Navbar /> : <div></div>}
      <Routes>
        <Route exact path='/' element={<Login />} />
        <Route exact element={<RequireAuth authID={{ id: 1 }} />}>
          <Route exact path='/teacher' element={<Teacher />} />
        </Route>
        <Route exact element={<RequireAuth authID={{ id: 2 }} />}>
          <Route exact path='/student' element={<Student />} />
        </Route>
      </Routes>
    </MantineProvider>
  );
}

export default InnerApp;

RequireAuth组件

const RequireAuth = (props) => {
  const { auth } = useContext(AuthContext);
  // console.log(props.authID.id);
  // console.log(auth?.id);
  return (
    auth?.id === props.authID?.id
      ? <Outlet />
      : <div>404 Cannot go to his link</div>
  )
}

export default RequireAuth

入口文件

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

function App() {
  return (
    <AuthProvider>
      <InnerApp />
    </AuthProvider>
  );
}

Login组件

import AuthContext from "../context/AuthProvider";
import { useNavigate } from "react-router-dom";

function Login() {
    const { auth, setAuth } = useContext(AuthContext);
    const [username, setUsername] = useState();
    const [password, setPassword] = useState(); 
    const navigate = useNavigate();

    // 模拟认证逻辑,无需后端支持
    const handleSubmit = () => {
        if (username === "student") {
            setAuth({name: username, id: 2});
            navigate("/student");
        } else if (username === "teacher") {
            setAuth({name: username, id: 1});
            navigate("/teacher");
        }
    }
    const handleUsernameChange = (e) => {
        setUsername(e.currentTarget.value);
    }
    const handlePasswordChange = (e) => {
        setPassword(e.currentTarget.value);
    }

  return (
    <div> 
        <Input placeholder="Username" 
            onChange={handleUsernameChange}
        />
        <Input placeholder="Password"
            onChange={handlePasswordChange}
        />
        <button onClick={handleSubmit}>Submit</button>
    </div>
  );
}

export default Login;

解决方案

1. 阻止Link组件的默认跳转行为

Logout按钮使用了Link组件,点击时会触发其默认跳转逻辑(即便to为空,也会默认跳当前页面),导致navigate("/")被覆盖。修改handleLogout函数添加事件阻止:

const handleLogout = (e) => {
  e.preventDefault(); // 阻止Link默认跳转
  setAuth(null);
  navigate("/");
  console.log("logout has been clicked");
};

或者直接将Logout的Link替换为普通button元素,避免默认路由行为干扰:

<li><button onClick={handleLogout}>Logout</button></li>

2. 移除冗余的exact属性

react-router-dom v6版本中,Route默认采用精确匹配,无需手动添加exact属性,移除后可简化配置并避免潜在匹配问题:

<Routes>
  <Route path='/' element={<Login />} />
  <Route element={<RequireAuth authID={{ id: 1 }} />}>
    <Route path='/teacher' element={<Teacher />} />
  </Route>
  <Route element={<RequireAuth authID={{ id: 2 }} />}>
    <Route path='/student' element={<Student />} />
  </Route>
</Routes>

3. 验证AuthContext状态更新逻辑

确保AuthProvider中的setAuth是通过useState创建的,状态更新能触发InnerApp重渲染,从而隐藏Navbar并显示Login页面。示例AuthProvider实现:

import { createContext, useState } from "react";

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [auth, setAuth] = useState(null);

  return (
    <AuthContext.Provider value={{ auth, setAuth }}>
      {children}
    </AuthContext.Provider>
  );
};

export default AuthContext;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:35:04