React Router DOM导航后不渲染组件问题求助
问题描述
在React应用中使用react-router-dom@6.23.1配置基础路由,ProtectedRoutes中的Navigate组件可完成导航,但页面无内容渲染。将Route标签移出嵌套路由后功能正常,控制台无报错,需解决该问题。
现有代码
ProtectedRoutes.tsx
const ProtectedRoutes = () => { let token = localStorage.getItem("token") var currentLocation = window.location.href if(token) { const decoded = (jwtDecode(token) as any) if(decoded.signup_completed) { if( currentLocation.endsWith("/login") || currentLocation.endsWith("/forgot-password") || currentLocation.endsWith("/reset-password") || currentLocation.endsWith("/signup") ) { return <Navigate to='/'></Navigate> } } else { if(decoded.signup_step === 2) { return <Navigate to='/signup/company'></Navigate> } else if(decoded.signup_step === 3) { return <Navigate to='/signup/company/detail'></Navigate> } } } else { if(currentLocation.endsWith('/login') || currentLocation.endsWith('/signup') || currentLocation.endsWith('/reset-password') || currentLocation.endsWith('/forgot-password')) { return <Outlet></Outlet> } return <Navigate to='/login'></Navigate> } return <Outlet></Outlet> } export default ProtectedRoutes
App.tsx
function App() { return ( <Router> <Routes> <Route element={<ProtectedRoutes></ProtectedRoutes>}> <Route index element={<Clients></Clients>} /> <Route path="/login" element={<Login></Login>} /> <Route path="/signup" element={<Signup></Signup>} /> <Route path="/signup/company" element={<SignupCompany></SignupCompany>} /> <Route path="/signup/company/detail" element={<SignupCompanyDetail></SignupCompanyDetail>} /> </Route> </Routes> </Router> ); } export default App;
问题分析与修复方案
核心问题1:嵌套路由使用绝对路径
react-router-dom v6中,嵌套路由的子Route如果使用绝对路径(如path="/login"),会被当作根级别路由处理,不会匹配父路由的Outlet,导致页面内容无法渲染。
核心问题2:路由路径判断方式不可靠
通过window.location.href解析路径容易出错(比如URL带参数、哈希值时),应该使用React Router提供的useLocation钩子获取当前路由路径。
修复后的代码
ProtectedRoutes.tsx
import { Outlet, Navigate, useLocation } from 'react-router-dom'; import jwtDecode from 'jwt-decode'; const ProtectedRoutes = () => { const token = localStorage.getItem("token"); const location = useLocation(); const currentPath = location.pathname; if (token) { const decoded = jwtDecode(token) as any; if (decoded.signup_completed) { const authPaths = ['/login', '/forgot-password', '/reset-password', '/signup']; if (authPaths.includes(currentPath)) { return <Navigate to='/' replace />; } } else { if (decoded.signup_step === 2) { return <Navigate to='/signup/company' replace />; } else if (decoded.signup_step === 3) { return <Navigate to='/signup/company/detail' replace />; } } } else { const publicPaths = ['/login', '/signup', '/reset-password', '/forgot-password']; if (publicPaths.includes(currentPath)) { return <Outlet />; } return <Navigate to='/login' replace />; } return <Outlet />; }; export default ProtectedRoutes;
App.tsx
import { Router, Routes, Route } from 'react-router-dom'; import ProtectedRoutes from './ProtectedRoutes'; import Clients from './Clients'; import Login from './Login'; import Signup from './Signup'; import SignupCompany from './SignupCompany'; import SignupCompanyDetail from './SignupCompanyDetail'; function App() { return ( <Router> <Routes> <Route element={<ProtectedRoutes />}> <Route index element={<Clients />} /> <Route path="login" element={<Login />} /> <Route path="signup" element={<Signup />} /> <Route path="signup/company" element={<SignupCompany />} /> <Route path="signup/company/detail" element={<SignupCompanyDetail />} /> </Route> </Routes> </Router> ); } export default App;
关键修复点
- 嵌套路由路径改为相对路径:去掉子
Route的path开头的/,让React Router将其识别为父路由的子路径,确保内容能通过父组件的Outlet渲染。 - 用
useLocation替代window.location.href:直接获取路由的pathname,避免URL解析错误,路径判断更准确。 - 添加
replace属性到Navigate:导航时替换当前历史记录,避免生成多余的历史条目,优化用户回退体验。
内容的提问来源于stack exchange,提问作者kemalkaancetindag
相关产品推荐
相关产品推荐

