路由是通过渲染<Routes>
和<Route>
来配置的,它们将 URL 片段与 UI 元素关联起来。
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router";
import App from "./app";
const root = document.getElementById("root");
ReactDOM.createRoot(root).render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
</Routes>
</BrowserRouter>
);
这是一个更大的示例配置
<Routes>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route element={<AuthLayout />}>
<Route path="login" element={<Login />} />
<Route path="register" element={<Register />} />
</Route>
<Route path="concerts">
<Route index element={<ConcertsHome />} />
<Route path=":city" element={<City />} />
<Route path="trending" element={<Trending />} />
</Route>
</Routes>
路由可以嵌套在父路由中。
<Routes>
<Route path="dashboard" element={<Dashboard />}>
<Route index element={<Home />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
父路由的路径会自动包含在子路由中,因此此配置创建了"/dashboard"
和"/dashboard/settings"
这两个 URL。
子路由通过父路由中的<Outlet/>
进行渲染。
import { Outlet } from "react-router";
export default function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
{/* will either be <Home/> or <Settings/> */}
<Outlet />
</div>
);
}
没有path
属性的路由会为其子路由创建新的嵌套,但它们不会向 URL 添加任何片段。
<Routes>
<Route element={<MarketingLayout />}>
<Route index element={<MarketingHome />} />
<Route path="contact" element={<Contact />} />
</Route>
<Route path="projects">
<Route index element={<ProjectsHome />} />
<Route element={<ProjectsLayout />}>
<Route path=":pid" element={<Project />} />
<Route path=":pid/edit" element={<EditProject />} />
</Route>
</Route>
</Routes>
索引路由在其父路由的 URL 上(类似于默认子路由)渲染到其父路由的<Outlet/>
中。它们使用index
属性进行配置。
<Routes>
<Route path="/" element={<Root />}>
{/* renders into the outlet in <Root> at "/" */}
<Route index element={<Home />} />
<Route path="dashboard" element={<Dashboard />}>
{/* renders into the outlet in <Dashboard> at "/dashboard" */}
<Route index element={<DashboardHome />} />
<Route path="settings" element={<Settings />} />
</Route>
</Route>
</Routes>
请注意,索引路由不能有子路由。如果您期望这种行为,您可能需要一个布局路由。
没有element
属性的<Route path>
会为其子路由添加路径前缀,而不会引入父布局。
<Route path="projects">
<Route index element={<ProjectsHome />} />
<Route element={<ProjectsLayout />}>
<Route path=":pid" element={<Project />} />
<Route path=":pid/edit" element={<EditProject />} />
</Route>
</Route>
如果路径片段以:
开头,则它会变成一个“动态片段”。当路由匹配 URL 时,动态片段将从 URL 中解析出来,并作为params
提供给其他路由 API,例如useParams
。
<Route path="teams/:teamId" element={<Team />} />
import { useParams } from "react-router";
export default function Team() {
let params = useParams();
// params.teamId
}
您可以在一个路由路径中拥有多个动态片段。
<Route
path="/c/:categoryId/p/:productId"
element={<Product />}
/>
import { useParams } from "react-router";
export default function Team() {
let { categoryId, productId } = useParams();
// ...
}
您可以通过在片段末尾添加?
来使路由片段可选。
<Route path=":lang?/categories" element={<Categories />} />
您也可以拥有可选的静态片段。
<Route path="users/:userId/edit?" component={<User />} />
也称为“捕获所有”和“星号”片段。如果路由路径模式以/*
结尾,则它将匹配/
之后的任何字符,包括其他/
字符。
<Route path="files/*" element={<File />} />
let params = useParams();
// params["*"] will contain the remaining URL after files/
let filePath = params["*"];
您可以解构*
,您只需要为其分配一个新名称即可。一个常见的名称是splat
。
let { "*": splat } = useParams();
使用Link
和NavLink
从您的 UI 链接到路由。
import { NavLink, Link } from "react-router";
function Header() {
return (
<nav>
{/* NavLink makes it easy to show active states */}
<NavLink
to="/"
className={({ isActive }) =>
isActive ? "active" : ""
}
>
Home
</NavLink>
<Link to="/concerts/salt-lake-city">Concerts</Link>
</nav>
);
}