如何将React路由中的Layout组件设置为私有(需认证访问)
解决方案
1. 创建权限控制组件 RequireAuth
这个组件会检查用户的认证状态,仅在存在有效token时渲染受保护的Layout组件,否则跳转至登录页:
import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import Layout from './Layout'; // 导入你的Layout组件 const RequireAuth = () => { const navigate = useNavigate(); // 从localStorage读取token(根据你的实际存储方式调整) const token = localStorage.getItem('authToken'); useEffect(() => { if (!token) { // 跳转登录页时记录当前路径,方便登录后返回 navigate('/login', { state: { from: window.location.pathname } }); } }, [token, navigate]); // 有token则渲染Layout,无token时暂时返回加载提示 return token ? <Layout /> : <div>加载中...</div>; }; export default RequireAuth;
2. 确保Layout组件包含<Outlet />
你的Layout必须通过<Outlet />渲染子路由内容,否则子组件无法正常显示:
import { Outlet } from 'react-router-dom'; const Layout = () => { return ( <div className="layout-container"> {/* 这里放你的导航栏、侧边栏等公共布局元素 */} <header>网站导航</header> {/* 子路由内容会渲染在这个位置 */} <main> <Outlet /> </main> </div> ); }; export default Layout;
3. 修改路由配置
将原来父路由的element替换为RequireAuth,让所有子路由都经过权限校验:
import { createBrowserRouter } from 'react-router-dom'; import RequireAuth from './RequireAuth'; import Home from './Home'; import Users from './Users'; import Products from './Products'; import Profile from './Profile'; import Login from './Login'; import SignUp from './SignUp'; const router = createBrowserRouter([ { path: "/", element: <RequireAuth />, // 用权限组件替代直接渲染Layout children: [ { path: "/", element: <Home /> }, { path: "/users", element: <Users /> }, { path: "/products", element: <Products /> }, { path: "/profile", element: <Profile /> } ] }, { path: "/login", element: <Login /> }, { path: "/register", element: <SignUp /> }, ]); export default router;
4. 登录后跳转回原页面(可选)
在Login组件中,登录成功后可以跳转到用户原本想要访问的页面:
import { useNavigate, useLocation } from 'react-router-dom'; const Login = () => { const navigate = useNavigate(); const location = useLocation(); // 获取跳转前的路径,默认回到首页 const from = location.state?.from || '/'; const handleLogin = async (formData) => { // 调用登录接口获取token const response = await fetch('/api/login', { method: 'POST', body: JSON.stringify(formData), headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.token) { localStorage.setItem('authToken', data.token); // 跳转到用户原本想访问的页面 navigate(from); } }; return ( <div> <form onSubmit={(e) => { e.preventDefault(); handleLogin(e.target); }}> {/* 登录表单字段 */} <input type="text" name="username" placeholder="用户名" /> <input type="password" name="password" placeholder="密码" /> <button type="submit">登录</button> </form> </div> ); }; export default Login;
内容的提问来源于stack exchange,提问作者El Gueddari Ayoub
相关产品推荐
相关产品推荐

