React Router v6中如何根据认证状态实现路由重定向?
如何根据用户认证状态实现页面重定向?
我配置了多个不同的路由,以下是App.js代码:
import React from 'react' import AuthContextProvider from './Contexts/AuthContext' import RootContextProvider from './Contexts/RootContext' import { BrowserRouter, Routes, Route } from 'react-router-dom' import Browse from './Routes/Private/Browse/Browse' import LandingPage from './Routes/LandingPage' import Login from './Routes/Login' import ScrollToTop from './ScrollToTop' import Home from './Routes/Private/Browse/Outlets/Home' import TVShows from './Routes/Private/Browse/Outlets/TVShows' import Latest from './Routes/Private/Browse/Outlets/Latest' import MyList from './Routes/Private/Browse/Outlets/MyList' import Movies from './Routes/Private/Browse/Outlets/Movies' import Title from './Routes/Private/Browse/Title' function App() { return ( <BrowserRouter> <AuthContextProvider> <RootContextProvider> <Routes> // Public routes here <Route path='/' element={<LandingPage />} /> <Route path='/login' element={<Login />} /> // Public routes here // Private routes here <Route path='/browse' element={<Browse />}> <Route index element={<Home />} /> <Route path='tv-shows' element={<TVShows />} /> <Route path='movies' element={<Movies />} /> <Route path='latest' element={<Latest />} /> <Route path='my-list' element={<MyList />} /> </Route> <Route path='movie/:id' element={<Title />} /> <Route path='tv/:id' element={<Title />} /> // Private routes here </Routes> <ScrollToTop /> </RootContextProvider> </AuthContextProvider> </BrowserRouter> ) } export default App
我划分了私有路由(Private routes)和公共路由(Public routes),希望根据auth上下文实现以下重定向规则:
- 当
auth === true时:- 用户访问任意公共路由时,重定向到
/browse - 用户访问未找到的路由(not found route)时,重定向到
/browse
- 用户访问任意公共路由时,重定向到
- 当
auth === false时:- 用户访问任意私有路由时,重定向到
/login - 用户访问未找到的路由时,重定向到
/
- 用户访问任意私有路由时,重定向到
所有私有路由仅在
auth === true时可访问,所有公共路由仅在auth === false时可访问
解决方案
1. 创建路由保护组件
分别创建两个路由包装组件,用来处理不同认证状态下的路由访问权限:
PrivateRoute.jsx(保护私有路由)
import React, { useContext } from 'react' import { Navigate, Outlet } from 'react-router-dom' import { AuthContext } from './Contexts/AuthContext' export default function PrivateRoute() { const { auth } = useContext(AuthContext) // 已认证则渲染子路由/组件,未认证则重定向到登录页 return auth ? <Outlet /> : <Navigate to="/login" replace /> }
PublicRoute.jsx(限制公共路由仅未认证用户访问)
import React, { useContext } from 'react' import { Navigate, Outlet } from 'react-router-dom' import { AuthContext } from './Contexts/AuthContext' export default function PublicRoute() { const { auth } = useContext(AuthContext) // 未认证则渲染子路由/组件,已认证则重定向到browse页面 return !auth ? <Outlet /> : <Navigate to="/browse" replace /> }
2. 修改App.js的路由配置
将原有路由按公共/私有分类,用保护组件包裹,并添加404路由处理:
import React, { useContext } from 'react' import AuthContextProvider from './Contexts/AuthContext' import RootContextProvider from './Contexts/RootContext' import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom' import Browse from './Routes/Private/Browse/Browse' import LandingPage from './Routes/LandingPage' import Login from './Routes/Login' import ScrollToTop from './ScrollToTop' import Home from './Routes/Private/Browse/Outlets/Home' import TVShows from './Routes/Private/Browse/Outlets/TVShows' import Latest from './Routes/Private/Browse/Outlets/Latest' import MyList from './Routes/Private/Browse/Outlets/MyList' import Movies from './Routes/Private/Browse/Outlets/Movies' import Title from './Routes/Private/Browse/Title' import PrivateRoute from './PrivateRoute' import PublicRoute from './PublicRoute' function App() { const { auth } = useContext(AuthContext) return ( <BrowserRouter> <AuthContextProvider> <RootContextProvider> <Routes> {/* 公共路由:仅未认证用户可访问 */} <Route element={<PublicRoute />}> <Route path='/' element={<LandingPage />} /> <Route path='/login' element={<Login />} /> </Route> {/* 私有路由:仅已认证用户可访问 */} <Route element={<PrivateRoute />}> <Route path='/browse' element={<Browse />}> <Route index element={<Home />} /> <Route path='tv-shows' element={<TVShows />} /> <Route path='movies' element={<Movies />} /> <Route path='latest' element={<Latest />} /> <Route path='my-list' element={<MyList />} /> </Route> <Route path='movie/:id' element={<Title />} /> <Route path='tv/:id' element={<Title />} /> </Route> {/* 404路由:根据认证状态重定向 */} <Route path='*' element={ auth ? <Navigate to="/browse" replace /> : <Navigate to="/" replace /> } /> </Routes> <ScrollToTop /> </RootContextProvider> </AuthContextProvider> </BrowserRouter> ) } export default App
3. 确保AuthContext正确提供状态
你的AuthContext需要正确暴露auth状态,示例如下(AuthContext.js):
import React, { createContext, useState, useEffect } from 'react' export const AuthContext = createContext() export default function AuthContextProvider({ children }) { const [auth, setAuth] = useState(false) // 初始化时读取本地存储的认证状态(可根据实际逻辑调整) useEffect(() => { const isAuthenticated = localStorage.getItem('isAuthenticated') === 'true' setAuth(isAuthenticated) }, []) return ( <AuthContext.Provider value={{ auth, setAuth }}> {children} </AuthContext.Provider> ) }
关键说明
replace属性:重定向后不会在浏览器历史记录中保留原路由,避免用户通过后退按钮回到受限页面Outlet组件:react-router-dom v6中嵌套路由的核心,用于渲染子路由内容- 404路由
path='*':匹配所有未定义的路由,根据当前认证状态执行对应重定向
内容的提问来源于stack exchange,提问作者Ram Farid
相关产品推荐
相关产品推荐

