В этом руководстве мы узнаем, как создавать вложенные маршруты с помощью React Router v6.
Вот так выглядит наш окончательный результат.
Прежде всего, мы создадим 2 компонента: один для дома, а другой для пользователя.
Теперь создадим 2 новых роутера и добавим для них навигацию в App.Js. Мы создадим еще 2 компонента, кроме упомянутых выше, один для Layout и один для NotFound.
import { Link, Routes, Route, BrowserRouter as Router } from 'react-router-dom'; import Home from './components/Home'; import NotFound from './components/NotFound'; import User from './components/User'; import Layout from './components/Layout'; import './App.css'; const App = () => { return ( <Router> <h1>React Router</h1> <nav> <Link to="/home">Home</Link> <Link to="/user">User</Link> </nav> <Routes> <Route element={<Layout />}> <Route index element={<Home />} /> <Route path="home" element={<Home />} /> <Route path="user" element={<User />} /> <Route path="*" element={<NotFound />} /> </Route> </Routes> </Router> ); }
В этом функциональном компоненте у нас есть соответствующий компонент Link и Route из React Router для маршрутов /home и /user. Затем у нас есть индексный маршрут, загруженный с помощью компонента Home, и маршрут NoFound / WildCard, загруженный с компонентом NotFound.
Оба работают как резервные компоненты.
Вложенные маршруты
В User Component мы добавим вложенную маршрутизацию. Итак, мы добавим компоненты Link, которые будут направлять пользователя к его профилю и транзакциям.
import React from 'react'; import { Link } from 'react-router-dom'; const User = () => { return ( <> <h1>User</h1> <nav> <Link to="profile">Profile</Link> <Link to="transactions">Transactions</Link> </nav> </> ) } export default User;
Если мы нажмем одну из этих ссылок, мы будем перенаправлены на маршрут NotFound. Это означает, что мы еще не сопоставили эти маршруты (/user/profile, /user/transactions) с фактическим компонентом маршрута. Поэтому мы добавим эти вложенные маршруты в наши маршруты /user.
import { Link, Routes, Route, BrowserRouter as Router } from 'react-router-dom'; import Home from './components/Home'; import NotFound from './components/NotFound'; import User from './components/User'; import Layout from './components/Layout'; import Profile from './components/Profile'; import Transactions from './components/Transactions'; const App = () => { return ( <Router> <h1>React Router</h1> <nav> <Link to="/home">Home</Link> <Link to="/user">User</Link> </nav> <Routes> <Route element={<Layout />}> <Route index element={<Home />} /> <Route path="home" element={<Home />} /> <Route path="user" element={<User />}> <Route path="profile" element={<Profile />} /> <Route path="transactions" element={<Transactions />} /> </Route> <Route path="*" element={<NotFound />} /> </Route> </Routes> </Router> ); } export default App;
Компоненты Route сопоставляются с компонентами Link в отношениях один к одному. Однако может быть более одного компонента Link, связанного с одним и тем же маршрутом, поэтому на самом деле это отношение «один ко многим».
Если мы проверим это сейчас в браузере, мы увидим, что в браузере отображается только пользовательский компонент, а не его вложенный компонент, который является профилем и транзакциями, которые нажимают на соответствующие ссылки.
Чтобы это заработало, нам нужно добавить компонент Outlet из React Router.
import React from 'react'; import { Link, Outlet } from 'react-router-dom'; const User = () => { return ( <> <h2>User</h2> <nav> <Link to="profile">Profile</Link> <Link to="transactions">Transactions</Link> </nav> <Outlet /> </> ) } export default User;
Компонент Outlet визуализирует соответствующий дочерний маршрут с соответствующим компонентом (здесь либо компонент Profile, либо компонент Transactions) из родительской коллекции компонентов Routes.
Если нет соответствующего маршрута /profile или /transactions (например, /user/profile), мы увидим только компонент User. Итак, чтобы избежать этого, мы можем добавить index и NotFound Route. Теперь маршрут по умолчанию будет Profile.
const App = () => { return ( <Router> <h1>React Router</h1> <nav> <Link to="/home">Home</Link> <Link to="/user">User</Link> </nav> <Routes> <Route element={<Layout />}> <Route index element={<Home />} /> <Route path="home" element={<Home />} /> <Route path="user" element={<User />}> <Route index element={<Profile />} /> <Route path="profile" element={<Profile />} /> <Route path="transactions" element={<Transactions />} /> <Route path="*" element={<NotFound />} /> </Route> <Route path="*" element={<NotFound />} /> </Route> </Routes> </Router> ); }
Вот и все. Хотя компонент User всегда отображает навигацию, его содержимое (Outlet) заменяется соответствующим вложенным маршрутом (либо компонентом Profile, либо компонентом Transactions на основе маршрута /user/profile
или /user/transactions
). Если ни один из этих маршрутов не соответствует при посещении маршрута /user
, приложение отобразит компонент «Профиль» (если маршрут точно соответствует /user
) или компонент «Несоответствие» (если маршрут не совпадает, например, /user/setting
).
Динамический вложенный маршрут
В этом разделе мы будем отображать динамический вложенный маршрут на основе идентификаторов /user/transactions/1 (детали транзакций с идентификатором транзакции 1).
Начнем с инициализации списка транзакций в нашем компоненте приложения. Это всего лишь простые данные, но их можно получить из удаленного API. Мы передадим эти данные в компонент транзакций в качестве реквизита.
const App = () => { const transactions = [ { id: '1', details: 'Transaction 1' }, { id: '2', details: 'Transactions 2' }, ]; return ( <Router> <h1>React Router</h1> <nav> <Link to="/home">Home</Link> <Link to="/user">User</Link> </nav> <Routes> <Route element={<Layout />}> <Route index element={<Home />} /> <Route path="home" element={<Home />} /> <Route path="user" element={<User />}> <Route index element={<Profile />} /> <Route path="profile" element={<Profile />} /> <Route path="transactions" element={<Transactions transactions={transactions} />} /> <Route path="*" element={<NotFound />} /> </Route> <Route path="*" element={<NotFound />} /> </Route> </Routes> </Router> ); }
Компонент транзакций здесь становится компонентом списка, где мы будем показывать список транзакций для пользователя, использующего компонент Link. Относительный путь в компоненте Link намекает на соответствующий вложенный (здесь: /${transaction.id}
, вложенный в /user/transactions
), но динамический (здесь: /${transaction.id}
) маршрут.
const Transactions = ({ transactions }) => { return ( <> <h2>Transactions</h2> <ul> {transactions.map((transaction) => ( <li key={transaction.id}> <Link to={transaction.id}> {transaction.details} </Link> </li> ))} </ul> </> ) }
Теперь нам нужно создать соответствующий вложенный маршрут в компоненте приложения. Во-первых, это вложенный маршрут для /user/transactions, мы можем поместить его в соответствующий родительский компонент маршрута. Во-вторых, это динамический маршрут, он использует динамический маршрут, который определяется как :transactionId
, где идентификатор транзакции является динамическим.
Теперь мы добавим компонент Outlet в компонент Transactions, чтобы он мог отображать совпадающий дочерний маршрут.
const Transactions = ({ transactions }) => { return ( <> <h2>Transactions</h2> <ul> {transactions.map((transaction) => ( <li key={transaction.id}> <Link to={transaction.id}> {transaction.details} </Link> </li> ))} </ul> <Outlet /> </> ) }
Теперь мы создадим компонент транзакций, который будет отображаться в компоненте транзакций через Outlet всякий раз, когда есть соответствующий маршрут.
import React from 'react'; import { Link, useParams } from 'react-router-dom'; const Transaction = () => { const { transactionId } = useParams(); return ( <> <h2>Transaction Id: { transactionId }</h2> <Link to={-1}>Back to Transactions</Link> </> ) } export default Transaction;
Вот и все. В компоненте транзакции мы получаем идентификатор транзакции через useParam Hook, который мы определили как динамический в компоненте приложения.
Согласно документу React Router
Хук
useParams
возвращает объект пар ключ/значение динамических параметров из текущего URL, которые были сопоставлены<Route path>
. Дочерние маршруты наследуют все параметры родительских маршрутов.
Также мы добавили ссылку Назад к транзакциям в компоненте транзакций, которая будет перенаправлять обратно на маршрут /user/transactions.
Это. В этой статье мы увидели, как создавать вложенные маршруты и динамические маршруты с помощью реактивного маршрутизатора.
Вложенные маршруты и динамические маршруты помогут вам улучшить ваш опыт и поддерживать структурированные маршруты.
Если вам это понравилось, пожалуйста, хлопните в ладоши.
Исходный код: https://github.com/piyush303/react-router-v6-nested-routes-demo
Демо: https://codesandbox.io/s/nested-dynamic-routes-using-react-router-v6-9gs2uq
Дайте нам знать, какую тему вы хотите, чтобы мы осветили в следующих статьях.