使用的是
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 组件。