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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 06:55:22