常见的 Router
库有:
本节以 react-router@7
为例,介绍如何在 React
中使用路由。
1.Mode
react-router
支持 3
种模式,功能由简单到复杂分别为:
Declarative
:声明式路由,使用JSX
语法定义路由。Data
:对象式路由,使用对象定义路由。Framework
:框架式路由,使用框架的方式定义路由。区分CSR
、SSG
以及SSR
。
2.Create a Router and Render
bash
pnpm add react-router@7
然后在 React
中创建一个路由并渲染:
tsx
import {
createBrowserRouter,
RouterProvider,
} from "react-router";
import React from "react";
import ReactDOM from "react-dom/client";
const router = createBrowserRouter([
{
path: "/",
element: <div>Hello World</div>,
},
]);
const root = document.getElementById("root");
ReactDOM.createRoot(root).render(
<RouterProvider router={router} />
);
3.createBrowserRouter
tsx
createBrowserRouter([
{
path: "/",
Component: Root,
children: [
{ index: true, Component: Home },
{ path: "about", Component: About },
{
path: "auth",
Component: AuthLayout,
children: [
{ path: "login", Component: Login },
{ path: "register", Component: Register },
],
},
{
path: "concerts",
children: [
{ index: true, Component: ConcertsHome },
{ path: ":city", Component: ConcertsCity },
{ path: "trending", Component: ConcertsTrending },
],
},
{
path: "/teams/:teamId",
loader: async ({ params }) => {
let team = await fetchTeam(params.teamId);
return { name: team.name };
},
Component: Team,
},
{
path: "/lazy",
lazy: async () => {
// load component and loader in parallel before rendering
const [Component, loader] = await Promise.all([
import("./lazy"),
import("./lazy-loader"),
]);
return { Component, loader };
}
}
],
},
]);
function Team() {
let data = useLoaderData();
return <h1>{data.name}</h1>;
}
上面的代码中涉及到了嵌套路由,类似于 Vue
中的 router-view
,在 react
中我们需要使用 Outlet
组件来渲染子路由:
tsx
import { Outlet } from "react-router";
function Root() {
return (
<div>
<h1>Root</h1>
<Outlet />
</div>
);
}
4.Declarative Navigation
tsx
import { Link, NavLink } from 'react-router'
function Navbar() {
return (
<nav>
<Link to="/">首页</Link>
<NavLink to="/about">关于我们</NavLink>
</nav>
)
}
tsx
import { Navigate } from 'react-router-dom'
function LoginPage() {
const user = useAuth()
if (user) {
return <Navigate to="/dashboard" replace />
}
return <LoginForm />
}
- 在组件中返回
<Navigate />
会立即跳转到指定路由。 replace
表示替换浏览器历史记录(不会产生后退页面)。
5.Imperative Navigation
tsx
import { useNavigate } from 'react-router'
function LoginButton() {
const navigate = useNavigate()
const handleLogin = async () => {
const result = await login()
if (result.success) {
navigate('/dashboard?token=123') // 编程式跳转
}
}
return <button onClick={handleLogin}>登录</button>
}
js
navigate(to, {
replace?: boolean, // 是否替换历史记录(等于 <Navigate replace />)
state?: any, // 可以传递自定义状态,跳转后用 useLocation().state 获取
relative?: "path" | "route"
})
// /users/abc
useParams()
// /search?keyword=abc
useSearchParams()