React Router基础 #

一、React Router概述 #

1.1 什么是React Router #

React Router 是 React 生态中最流行的路由库,用于构建单页应用(SPA)的路由系统。

1.2 安装 #

bash
npm install react-router-dom

1.3 核心组件 #

组件 说明
BrowserRouter 路由容器
Routes 路由配置容器
Route 单个路由规则
Link 导航链接
Navigate 编程式导航

二、基本使用 #

2.1 路由配置 #

javascript
import { BrowserRouter, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/users" element={<Users />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

2.2 导航链接 #

javascript
import { Link, NavLink } from 'react-router-dom';

function Navbar() {
  return (
    <nav>
      {/* 普通链接 */}
      <Link to="/">首页</Link>
      <Link to="/about">关于</Link>
      
      {/* 导航链接(带激活状态) */}
      <NavLink
        to="/users"
        className={({ isActive }) => isActive ? 'active' : ''}
      >
        用户
      </NavLink>
    </nav>
  );
}

2.3 嵌套路由 #

javascript
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<Home />} />
          <Route path="about" element={<About />} />
          <Route path="users" element={<Users />}>
            <Route index element={<UserList />} />
            <Route path=":id" element={<UserDetail />} />
          </Route>
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

function Layout() {
  return (
    <div>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/about">关于</Link>
        <Link to="/users">用户</Link>
      </nav>
      <main>
        <Outlet />
      </main>
    </div>
  );
}

function Users() {
  return (
    <div>
      <h2>用户列表</h2>
      <Outlet />
    </div>
  );
}

三、路由参数 #

3.1 动态参数 #

javascript
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/users" element={<UserList />} />
        <Route path="/users/:id" element={<UserDetail />} />
        <Route path="/posts/:postId/comments/:commentId" element={<Comment />} />
      </Routes>
    </BrowserRouter>
  );
}

function UserDetail() {
  const { id } = useParams();
  
  return <div>用户ID: {id}</div>;
}

function Comment() {
  const { postId, commentId } = useParams();
  
  return (
    <div>
      文章ID: {postId}
      评论ID: {commentId}
    </div>
  );
}

3.2 查询参数 #

javascript
import { useSearchParams } from 'react-router-dom';

function SearchPage() {
  const [searchParams, setSearchParams] = useSearchParams();
  
  const query = searchParams.get('q') || '';
  const page = searchParams.get('page') || '1';
  const category = searchParams.get('category') || 'all';

  const handleSearch = (newQuery) => {
    setSearchParams({ q: newQuery, page: '1' });
  };

  const handlePageChange = (newPage) => {
    setSearchParams(prev => {
      prev.set('page', newPage);
      return prev;
    });
  };

  return (
    <div>
      <input
        value={query}
        onChange={(e) => handleSearch(e.target.value)}
      />
      <p>搜索: {query}</p>
      <p>页码: {page}</p>
      <p>分类: {category}</p>
    </div>
  );
}

3.3 State传递 #

javascript
function UserList() {
  const users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
  ];

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>
          <Link
            to={`/users/${user.id}`}
            state={{ from: 'list', user }}
          >
            {user.name}
          </Link>
        </li>
      ))}
    </ul>
  );
}

function UserDetail() {
  const location = useLocation();
  const { from, user } = location.state || {};

  return (
    <div>
      <p>来源: {from}</p>
      <p>用户: {user?.name}</p>
    </div>
  );
}

四、编程式导航 #

4.1 useNavigate #

javascript
import { useNavigate } from 'react-router-dom';

function LoginForm() {
  const navigate = useNavigate();

  const handleSubmit = async (credentials) => {
    const success = await login(credentials);
    
    if (success) {
      navigate('/dashboard');
      // 或带参数
      navigate('/dashboard', { replace: true });
      // 或返回上一页
      navigate(-1);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* ... */}
    </form>
  );
}

4.2 Navigate组件 #

javascript
function ProtectedRoute({ children }) {
  const { user } = useAuth();

  if (!user) {
    return <Navigate to="/login" replace />;
  }

  return children;
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route
          path="/dashboard"
          element={
            <ProtectedRoute>
              <Dashboard />
            </ProtectedRoute>
          }
        />
      </Routes>
    </BrowserRouter>
  );
}

五、路由守卫 #

5.1 权限控制 #

javascript
function RequireAuth({ children }) {
  const { user } = useAuth();
  const location = useLocation();

  if (!user) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  return children;
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route
          path="/admin"
          element={
            <RequireAuth>
              <AdminPanel />
            </RequireAuth>
          }
        />
      </Routes>
    </BrowserRouter>
  );
}

5.2 角色权限 #

javascript
function RequireRole({ children, allowedRoles }) {
  const { user } = useAuth();

  if (!user) {
    return <Navigate to="/login" replace />;
  }

  if (!allowedRoles.includes(user.role)) {
    return <Navigate to="/forbidden" replace />;
  }

  return children;
}

function App() {
  return (
    <Routes>
      <Route
        path="/admin"
        element={
          <RequireRole allowedRoles={['admin']}>
            <AdminPanel />
          </RequireRole>
        }
      />
    </Routes>
  );
}

六、404处理 #

6.1 捕获所有路由 #

javascript
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

function NotFound() {
  return (
    <div>
      <h1>404</h1>
      <p>页面不存在</p>
      <Link to="/">返回首页</Link>
    </div>
  );
}

七、路由配置对象 #

7.1 useRoutes #

javascript
import { useRoutes } from 'react-router-dom';

const routes = [
  {
    path: '/',
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      { path: 'about', element: <About /> },
      {
        path: 'users',
        children: [
          { index: true, element: <UserList /> },
          { path: ':id', element: <UserDetail /> }
        ]
      }
    ]
  }
];

function App() {
  const element = useRoutes(routes);
  return element;
}

7.2 createBrowserRouter #

javascript
import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      { path: 'about', element: <About /> },
      {
        path: 'users/:id',
        element: <UserDetail />,
        loader: async ({ params }) => {
          return fetch(`/api/users/${params.id}`);
        }
      }
    ]
  }
]);

function App() {
  return <RouterProvider router={router} />;
}

八、最佳实践 #

8.1 路由结构组织 #

javascript
// routes/index.jsx
export const routes = [
  {
    path: '/',
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      ...userRoutes,
      ...adminRoutes
    ]
  }
];

// routes/userRoutes.jsx
export const userRoutes = [
  {
    path: 'users',
    children: [
      { index: true, element: <UserList /> },
      { path: ':id', element: <UserDetail /> }
    ]
  }
];

8.2 懒加载路由 #

javascript
import { lazy, Suspense } from 'react';

const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<Loading />}>
        <Routes>
          <Route path="/dashboard" element={<Dashboard />} />
          <Route path="/settings" element={<Settings />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

九、总结 #

要点 说明
BrowserRouter 路由容器
Routes/Route 路由配置
Link/NavLink 导航链接
useParams 获取动态参数
useSearchParams 获取查询参数
useNavigate 编程式导航

核心原则:

  • 使用 BrowserRouter 包裹应用
  • 使用 Routes 和 Route 配置路由
  • 使用 Link 进行导航
  • 使用 useParams 获取路由参数
最后更新:2026-03-26