使用的是
BrowserRouter
,Routes
和Route
,这是react-router-dom
v5 和 v6 都支持的 API。这种方式的优点是路由配置和应用的其它部分是紧密集成的,这使得路由配置更加直观和易于理解
// router/index.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from '../components/Home';
import About from '../components/About';
import User from '../components/User';
import UserDetails from '../components/UserDetails';
function AppRouter() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user" element={<User />}>
<Route path=":id" element={<UserDetails />} />
</Route>
{/* 添加更多的 Route 组件以定义更多的路由 */}
</Routes>
</Router>
);
}
export default AppRouter;
// App.js
import AppRouter from './router';
function App() {
return <AppRouter />;
}
export default App;
react-router-dom 获取 params 和 query
import { useParams, useSearchParams } from 'react-router-dom';
function SomeComponent() {
// 获取路径参数
const params = useParams();
const userId = params.id;
// 获取查询参数
const [searchParams] = useSearchParams();
const someQuery = searchParams.get('someQuery');
// ...
}
注意,
setSearchParams
函数会替换所有的查询参数,如果你只想修改某个查询参数,你需要先获取当前的查询参数,然后修改它,然后再调用setSearchParams
。例如:
const [searchParams, setSearchParams] = useSearchParams();
const newSearchParams = new URLSearchParams(searchParams.toString());
newSearchParams.set('someParam', 'newValue');
setSearchParams(newSearchParams);
只有 someParam 参数会被修改,其它的查询参数会保持不变
react-router-dom v5 vs v6
// router/index.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from '../components/Home';
import About from '../components/About';
import User from '../components/User';
import UserDetails from '../components/UserDetails';
function AppRouter() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user" element={<User />}>
<Route path=":id" element={<UserDetails />} />
</Route>
{/* 添加更多的 Route 组件以定义更多的路由 */}
</Routes>
</Router>
);
}
export default AppRouter;
v5
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Home = () => <h1>Home</h1>;
const About = () => <h1>About</h1>;
const User = () => <h1>User</h1>;
const UserSettings = () => <h1>User Settings</h1>;
const App = () => (
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/user" component={User}>
<Route path="/user/settings" component={UserSettings} />
</Route>
</Switch>
</Router>
);
export default App;
outlet
Outlet
组件被用来渲染子路由。当你在一个路由组件中包含一个Outlet
组件时,它会自动渲染与当前 URL 匹配的子路由。
import { BrowserRouter as Router, Routes, Route, Outlet } from 'react-router-dom';
const Home = () => <h1>Home</h1>;
const About = () => <h1>About</h1>;
const User = () => (
<div>
<h1>User</h1>
<Outlet /> {/* 子路由将会在这里被渲染 */}
</div>
);
const UserDetails = () => <h1>User Details</h1>;
const App = () => (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user" element={<User />}>
<Route path=":id" element={<UserDetails />} />
</Route>
</Routes>
</Router>
);
export default App;
多个子路由但是不在一个页面
如果你有多个子路由,但它们不应该在同一个页面上同时渲染,你可以使用
Routes
组件来包裹这些子路由。Routes
组件会渲染与当前 URL 匹配的第一个Route
组件。
import { BrowserRouter as Router, Routes, Route, Outlet } from 'react-router-dom';
const User = () => (
<div>
<h1>User</h1>
<Outlet /> {/* 子路由将会在这里被渲染 */}
</div>
);
const UserDetails = () => <h1>User Details</h1>;
const UserSettings = () => <h1>User Settings</h1>;
const App = () => (
<Router>
<Routes>
<Route path="/user" element={<User />}>
// 可省 <Routes>
<Route path="details" element={<UserDetails />} />
<Route path="settings" element={<UserSettings />} />
// </Routes>
</Route>
</Routes>
</Router>
);
export default App;
当你访问 /user/details 时,只有第一个匹配的子路由(UserDetails)
会被渲染在 Outlet 中。尽管你定义了两个与 /user/details 匹配的子路由,
但是 react-router-dom v6 只会渲染第一个匹配的 Route。
因此,无论你访问 /user/details,Outlet 都只会渲染 UserDetails 组件,
而不会渲染 UserSettings 组件。
这是因为 react-router-dom v6 的设计原则之一是:每个 URL 应该对应一个唯一的视图。
如果有多个 Route 与同一个 URL 匹配,那么只有第一个 Route 会被渲染。
你使用了嵌套的 Routes 组件来定义子路由,但这并不会改变路由的行为。
无论你是否使用嵌套的 Routes,react-router-dom 都会渲染与当前 URL
匹配的第一个 Route 组件。