React Router v6 引入了一个 Routes
组件,它有点像 Switch
,但功能要强大得多。与 Switch
相比, Routes
的主要优势在于:
<Routes>
中的所有<Route>
和<Link>
都是相对的。这导致在<Route path>
和<Link to>
中的代码更精简和更可预测。- 路由的选择基于最佳匹配,而不是按顺序遍历。这避免了由于在
<Switch>
中定义较晚而导致无法到达的错误。 - 路由可以嵌套在一个地方,而不是分散在不同的组件中。在中小型应用程序中,这样可以方便地一次性查看所有路由。在大型应用程序中,您仍然可以通过
React.lazy
动态加载将路由嵌套在打包中。
v6,您需要将所有 <Switch>
元素转换为 <Routes>
。
首先,让我们来谈谈 v6 中的相对路由和链接。
v5 是这样写:
// This is a React Router v5 app
import {
BrowserRouter,
Switch,
Route,
Link,
useRouteMatch,
} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/users">
<Users />
</Route>
</Switch>
</BrowserRouter>
);
}
function Users() {
// In v5, nested routes are rendered by the child component, so
// you have <Switch> elements all over your app for nested UI.
// You build nested routes and links using match.url and match.path.
let match = useRouteMatch();
return (
<div>
<nav>
<Link to={`${match.url}/me`}>My Profile</Link>
</nav>
<Switch>
<Route path={`${match.path}/me`}>
<OwnUserProfile />
</Route>
<Route path={`${match.path}/:id`}>
<UserProfile />
</Route>
</Switch>
</div>
);
}
v6需要这个样子:
// This is a React Router v6 app
import {
BrowserRouter,
Routes,
Route,
Link,
} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="users/*" element={<Users />} />
</Routes>
</BrowserRouter>
);
}
function Users() {
return (
<div>
<nav>
<Link to="me">My Profile</Link>
</nav>
<Routes>
<Route path=":id" element={<UserProfile />} />
<Route path="me" element={<OwnUserProfile />} />
</Routes>
</div>
);
}
v5 应用程序中的所有 <Route children>
在 v6 中都变为了 <Route element={}>
对于子路由,index设置为true时,相当于一个默认的子路由
关于 <Route path>
模式的注意事项
React Router v6 使用简化的路径格式。在 v6 中, <Route path>
只支持两种占位符:动态 :id
样式的参数和 *
通配符。 *
通配符只能在路径末尾使用,不能在中间使用。
/groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*
在 v6 中,无论当前 URL 如何, <Link to="me">
都会呈现相同的 <a href>
。
使用useRoutes
代替react-router-config
v5 版本的 react-router-config
包中的所有功能都已移至 v6 的核心中。如果您喜欢/需要将路由定义为 JavaScript 对象,而不是使用 React 元素,那么您一定会喜欢这个功能。
function App() {
let element = useRoutes([
// These are the same as the props you provide to <Route>
{ path: "/", element: <Home /> },
{ path: "dashboard", element: <Dashboard /> },
{
path: "invoices",
element: <Invoices />,
// Nested routes use a children property, which is also
// the same as <Route>
children: [
{ path: ":id", element: <Invoice /> },
{ path: "sent", element: <SentInvoices /> },
],
},
// Not found routes work as you'd expect
{ path: "*", element: <NotFound /> },
]);
// The returned element will render the entire element
// hierarchy with all the appropriate context it needs
return element;
}
使用useNavigate
代替useHistory
React Router v6 引入了新的导航 API,该 API 与 <Link>
同义,可更好地兼容启用了悬念的应用程序。根据您的风格和需求,我们提供了该 API 的命令式和声明式版本。
useHistory
更改为 useNavigate
,并更改 history.push
或 history.replace
调用站点。
// This is a React Router v6 app
import { useNavigate } from "react-router-dom";
function App() {
let navigate = useNavigate();
function handleClick() {
navigate("/home");
}
return (
<div>
<button onClick={handleClick}>go home</button>
</div>
);
}
注意:请注意,v5 版 <Redirect />
默认使用 replace
逻辑(可通过 push
属性进行更改),而 v6 版 <Navigate />
默认使用 push
逻辑,可通过 replace
属性进行更改。