React Router登录登出跳转后组件未正常渲染问题咨询
问题根因与修复方案
核心问题是前端路由跳转路径和路由表定义的路径完全不匹配,混淆了本地文件系统路径和react-router的前端路由路径,具体错误点:
- 路由表中明确定义Home组件对应路径为根路径
/,Login组件对应路径为/Login,但跳转时用了../Home、../pages/Login这类本地文件相对路径,根本无法命中已定义的路由规则,自然不会渲染对应组件。 - 登录逻辑里
navigate('../Home')从/Login路径解析后会跳转到/Home,该路径没有对应路由配置,所以Home组件不渲染。 - 登出逻辑里直接修改
window.location.pathname的写法不符合react-router的路由调度规则,且写入的../pages/Login是文件路径,解析后也无法命中/Login路由,同时这种写法会触发整页刷新,体验很差。 - 次要问题:Login组件接收了
isAuth入参,但路由配置时没有传递该参数,后续做权限判断会出问题;JSX中写class属性会触发React警告,需要替换为className。
第一步:调整入口文件,把Router移到外层
修改入口文件(通常是src/main.jsx/src/index.js),让整个App处于Router上下文内,这样App组件里才能正常调用useNavigate钩子:
import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter as Router } from 'react-router-dom'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <Router> <App /> </Router> );
第二步:修复Login组件跳转逻辑
把错误的相对路径跳转改成跳转到路由表定义的Home路径/,修复后代码:
import React from 'react'; import { auth, provider } from '../firebase-config'; import { signInWithPopup } from "firebase/auth"; import { useNavigate } from 'react-router-dom'; const Login = ({ isAuth, setIsAuth }) => { const navigate = useNavigate(); const signInWithGoogle = () => { signInWithPopup(auth, provider).then((result) => { localStorage.setItem("isAuth", true); setIsAuth(true); // 直接跳转到路由表定义的Home根路径 navigate('/'); }) } return ( <div className="ui container"> <p>Sign in with Google to continue</p> <button className="ui primary button" onClick={() => signInWithGoogle()}>Login</button> </div> ); }; export default Login;
第三步:修复App组件逻辑
移除App内部嵌套的Router,引入useNavigate替换原生window跳转,同时给Login组件补传isAuth参数,初始化状态时读取localStorage避免刷新后登录状态丢失,修复后代码:
import React from "react"; import Home from '../pages/Home'; import Login from '../pages/Login'; import { useState } from "react"; import { Routes, Route, Link, useNavigate } from "react-router-dom"; import { signOut } from "firebase/auth"; import { auth } from '../firebase-config'; const App = () => { const [isAuth, setIsAuth] = useState(Boolean(localStorage.getItem("isAuth"))); const navigate = useNavigate(); const signUserOut = () => { signOut(auth).then(() => { localStorage.clear(); setIsAuth(false); // 跳转到路由表定义的Login路径 navigate('/Login'); }) }; return ( <> <div className="ui secondary point menu"> <div className="ui container"> <Link className="active item" to="/"> <h4> Home </h4> </Link> {!isAuth ? <Link className="item" to="/Login"> <h4> Login </h4> </Link> : <span></span>} <div className="right menu"> <div className="item"> <div className="ui transparent icon input"> <input /> <i className="search link icon"></i> </div> </div> </div> </div> </div> <div className="ui container"> <div className="ui two column very relaxed stackable grid"> <div className="column"> {isAuth ? "You are signed in" : "You need to sign in"} </div> <div className="column"> {isAuth ? <button onClick={signUserOut}>Sign Out</button> : <span></span>} </div> </div> </div> <Routes> <Route path="/" element={<Home />} /> <Route path="/Login" element={<Login setIsAuth={setIsAuth} isAuth={isAuth} />} /> </Routes> </> ); }; export default App;
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

