React Router V6 新特性
安装
npm install react-router-dom@6
配置路由
import { render } from "react-dom";
import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";
// import your route components too
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route index element={<Home />} />
<Route path="teams" element={<Teams />}>
<Route path=":teamId" element={<Team />} />
<Route path="new" element={<NewTeamForm />} />
<Route index element={<LeagueStandings />} />
Route>
Route>
Routes>
BrowserRouter>,
document.getElementById("root")
);
在以前版本的 React Router 中,当多个路由匹配一个不明确的 URL 时,你必须以某种方式对你的路由进行排序才能得到正确的渲染。V6 更聪明,会选择最具体的匹配,所以你不必再担心了。例如,URL /teams/new
匹配这两个路由:
"teams/:teamId" element={} /> <Route path="teams/new" element={<NewTeamForm />} />
由于 teams/new
比 /teams/:teamId
是更具体的匹配 ,因此
将呈现。
导航
使用 Link 让用户更改 URL 或者用 useNavigate 自己做跳转:
import { Link } from "react-router-dom";
function Home() {
return (
<div>
<h1>Homeh1>
<nav>
<Link to="/">HomeLink> |{" "}
<Link to="about">AboutLink>
nav>
div>
);
}
import { useNavigate } from "react-router-dom";
function Invoices() {
let navigate = useNavigate();
return (
<div>
<NewInvoiceForm
onSubmit={async event => {
let newInvoice = await createInvoice(
event.target
);
navigate(`/invoices/${newInvoice.id}`);
}}
/>
div>
);
}
读取 URL 参数
在路由路径中使用 :style
语法,组件中用 useParams()
取值:
import { Routes, Route, useParams } from "react-router-dom";
function App() {
return (
<Routes>
<Route
path="invoices/:invoiceId"
element={<Invoice />}
/>
Routes>
);
}
function Invoice() {
let params = useParams();
return <h1>Invoice {params.invoiceId}h1>;
}
请注意,路径中 :invoiceId
和参数的键 params.invoiceId
匹配,key 值必须对应。
一个非常常见的用例是在组件呈现时获取数据:
function Invoice() {
let { invoiceId } = useParams();
let invoice = useFakeFetch(`/api/invoices/${invoiceId}`);
return invoice ? (
<div>
<h1>{invoice.customerName}h1>
div>
) : (
<Loading />
);
}
嵌套路由
这是 React Router 最强大的功能之一,因此您不必处理复杂的布局代码。绝大多数布局都与 URL 的片段耦合,而 React Router 完全符合了这一点。
路由可以相互嵌套,它们的路径也会嵌套(子继承父)。
function App() {
return (
"invoices" element={}>
":invoiceId" element={} />
"sent" element={} />
);
}
此路由配置定义了三个路由路径:
"/invoices"
"/invoices/sent"
"/invoices/:invoiceId"
当 URL 是"/invoices/sent", 组件树为:
当 URL 为"/invoices/123",组件树为:
请注意随 URL (
和
)更改的内部组件。父路由 (
) 负责确保匹配的子路由使用了
,这是完整的示例:
import { Routes, Route, Outlet } from "react-router-dom";
function App() {
return (
"invoices" element={}>
":invoiceId" element={} />
"sent" element={} />
);
}
function Invoices() {
return (
Invoices
);
}
function Invoice() {
let { invoiceId } = useParams();
return
Invoice {invoiceId}
;}
function SentInvoices() {
return
Sent Invoices
;}
嵌套的 url 路径映射到嵌套的组件树。这非常适合创建在布局中具有持久导航且内部部分随 URL 变化的 UI。您会注意到许多网站都具有多层布局嵌套。
索引路由
索引路由可以被认为是“默认子路由”。当父路由有多个子路由,但 URL 仅在父路由的路径上时,您可能希望将某些内容渲染到页面中。
function App() {
return (
"/" element={}>
"invoices" element={} />
"activity" element={} />
);
}
function Layout() {
return (
);
}
这个页面在“/invoices”和“/activity”上看起来很棒,但在“/”它只是一个空白页面, 因为那里没有子路由渲染。为此,我们可以添加一个索引路由:
function App() {
return (
"/" element={}>
} />
"invoices" element={} />
"activity" element={} />
);
}
现在在“/”处,
元素将在 Outlet 出口内呈现。
您可以在路由层次结构的任何级别拥有一个索引路由,当父级匹配但其他子级都不匹配时,该索引路由将呈现。
function App() {
return (
} />
"dashboard" element={}>
} />
path="invoices"
element={
} />
);
}
相对链接
相对 值(不以 / 开头)是相对于渲染它们的路径的路径。下面的两个链接将链接到 /dashboard/invoices 和 /dashboard/team 因为它们在
. 当您更改父级的 URL 或重新排列您的组件时,这非常好,因为您的所有链接都会自动更新。
import {
Routes,
Route,
Link,
Outlet
} from "react-router-dom";
function Home() {
return <h1>Homeh1>;
}
function Dashboard() {
return (
<div>
<h1>Dashboardh1>
<nav>
<Link to="invoices">InvoicesLink>{" "}
<Link to="team">TeamLink>
nav>
<hr />
<Outlet />
div>
);
}
function Invoices() {
return <h1>Invoicesh1>;
}
function Team() {
return <h1>Teamh1>;
}
function App() {
return (
} />
}>
} />
} />
);
}
"Not Found" 路由
当没有其他路由与 URL 匹配时,您可以使用path="*". 此路由将匹配任何 URL,但具有最弱的优先级,因此路由仅在没有其他路由匹配时才会选择它。
function App() {
return (
"/" element={} />
"dashboard" element={} />
"*" element={} />
);
}
多组路由
尽管您应该
在应用程序中只拥有一个,但您可以
在任何需要的地方拥有任意数量的。每个
元素独立于其他元素运行,并选择一个子路由进行渲染。
function App() {
return (
"/" element={} />
path="dashboard"
element={
} />
"/" element={}>
"about" element={} />
"support" element={} />
"dashboard" element={}>
"invoices" element={} />
"team" element={} />
"*" element={} />
);
}