Подробные примеры для React Router

Для веб-приложения маршрутизация — это механизм отображения всей или частичной страницы на основе предоставленного URL-адреса, параметров или действий пользователя с кнопкой, ссылкой, значком и т. д.

Сам React не включает маршрутизацию. react-router совместим с последними версиями React и является наиболее популярным выбором маршрутизации для приложений React. React Router позволяет перемещаться между представлениями различных компонентов. Он считывает и контролирует URL-адрес браузера, а также поддерживает синхронизацию пользовательского интерфейса с URL-адресом.

React Router 6 был выпущен 3 ноября 2021 года. Давайте подробно рассмотрим, как его использовать.

Терминология навигации

Во-первых, мы рассмотрим некоторые термины, которые часто используются при навигации в браузере.

URL-адрес

URL-адрес (унифицированный указатель ресурса) — это адрес данного уникального ресурса в Интернете. В браузере есть адресная строка, в которую пользователи могут вводить определенный URL-адрес или заполнять ее программно.

Интерфейс URL используется для анализа, создания, нормализации и кодирования URL-адресов. Он имеет ряд свойств, которые можно читать и изменять.

Создайте URL-адрес:

const url = new URL('https://john:[email protected]:8080/users/?id=5#profile');

Вот сгенерированный объект:

url.searchParams.get('id') возвращает 5.

Расположение

Местоположение — это объект, который представляет местоположение URL. Он основан на объекте window.location браузера.

Введите URL-адрес www.google.com в адресной строке браузера, а window.location будет установлено следующее значение:

Вот определения Path и Location в React Router:

История

Существует два API истории, которые отслеживают историю браузера и управляют ею:

  • history API: он отслеживает URL-адреса основного фрейма, которые пользователь посещал на любой вкладке в течение всего срока действия профиля.
  • History интерфейс: он управляет историей сеансов браузера. то есть он отслеживает навигацию на каждой вкладке.

Поскольку интерфейс History более осмыслен в современных браузерах, window.history включает запись для History. Вот пример window.history:

Вот определение History в React Router:

Настройка рабочей среды

React Router публикуется с 3 пакетами:

  • react-router содержит большую часть основных функций React Router, включая алгоритм сопоставления маршрутов и большинство основных компонентов и перехватчиков.
  • react-router-dom включает все из react-router и добавляет несколько специфичных для DOM API, включая <BrowserRouter>, <HashRouter> и <Link>.
  • react-router-native включает в себя все из react-router и добавляет несколько API, характерных для React Native, в том числе <NativeRouter> и нативную версию <Link>.

Для веб-приложений все, что нам нужно, это react-router-dom.

Как всегда, строим среду Create React App:

npx create-react-app react-router
cd react-router

Настройте react-router-dom:

npm i react-router-dom

Кроме того, устанавливается lorem-ipsum для генерации текста-заполнителя lorem ipsum для страниц. Текст Lorem ipsum обычно используется в качестве заполнителя в издательском деле, графическом дизайне и веб-разработке.

npm i lorem-ipsum

react-router-dom и lorem-ipsum становятся частью dependencies в package.json.

Настройка маршрутов

Router — это компонент верхнего уровня с отслеживанием состояния, который заставляет работать все остальные компоненты навигации и хуки. React Router имеет BrowserRouter, HashRouter, StaticRouter, NativeRouter и MemoryRouter. Для веб-приложений обычно используется BrowserRouter. Приложение должно иметь один <BrowserRouter>, обертывающий один или несколько <Routes>.

<Routes> проверяет все свои children <Route> элементы, чтобы найти наилучшее соответствие, и отображает эту часть пользовательского интерфейса.

<Route> определяется как объект или элемент маршрута. Если это объект, объект имеет форму { path, element }. Если это элемент Route, компонент имеет форму <Route path element>. Когда шаблон пути соответствует текущему URL-адресу, отображается реквизит element.

Подготавливаем несколько страниц для управления в src/Pages.js:

Строки 3–10 определяют функцию getPage. Он генерирует озаглавленную страницу, где содержимое страницы генерируется loremIpsum() с 5 случайными предложениями (строка 7).

Функция getPage используется для генерации PageOne (строка 12) и PageTwo (строка 13). Вот так выглядит PageOne, и PageTwo похоже.

В src/App.js создаются два маршрута:

<BrowserRouter> и <Routes> используются для определения маршрутизатора (строки 6–11).

В приложении есть два <Route>. Когда URL-адрес соответствует пути "one", приложение показывает PageOne (строка 8). Когда URL-адрес соответствует пути, "two", приложение показывает PageTwo (строка 9).

Запустите приложение, выполнив команду npm start.

https://localhost:3000/one показывает PageOne.

https://localhost:3000/two показывает PageTwo.

Приложение работает для путей "one" и "two". Однако https://localhost:3000 ничего не показывает, как и любые недопустимые URL-адреса, такие как https://localhost:3000/anything.

Эту проблему можно решить с помощью подстановочного пути (строка 8):

https://localhost:3000/two показывает PageTwo. В противном случае отображается PageOne.

Поскольку React Router 6 достаточно умен, чтобы выбрать наиболее точное совпадение, порядок маршрута не имеет значения.

Настройка вложенных маршрутов

Два маршрута в приведенном выше примере работают, как и ожидалось. Однако вводить URL-адрес в адресной строке браузера неудобно. Мы хотели бы иметь возможность навигации, нажав на ссылку, которая является <Link>.

<Link> отображает доступный элемент <a> с реальным href, указывающим на ресурс, на который он ссылается. Щелчок по ссылке устанавливает URL-адрес и отслеживает историю просмотров.

src/MainPage.js создается с помощью <Link>s:

Строки 4–13 определяют элемент <nav> с набором навигационных ссылок.

Строка 7 — это ссылка, указывающая на путь "/one". Текст ссылки "Page One".

Строка 10 — это ссылка, указывающая на путь "/two". Текст ссылки "Page Two".

Значения <Link to> могут относиться к пути маршрута, который их отображает. т. е. путь указан без ведущего /. Альтернативно, строка 7 может указывать на "one", а строка 10 может указывать на "two".

Используйте MainPage в src/App.js:

Строка 9 — это маршрут index, который является дочерним маршрутом без пути. Когда URL соответствует "/", приложение показывает MainPage. Вот индексная страница:

Нажав на ссылку Page One, вы попадете на PageOne. Нажав на ссылку Page Two, вы попадете на PageTwo.

Однако внутри PageOne или PageTwo мы не можем использовать ссылки для навигации. Чтобы решить эту проблему, мы создаем компонент <Outlet> в MainPage. Выходной компонент отображает следующее совпадение ("one" для PageTwo и "two" для PageTwo) в пути.

Это src/MainPage.js с розеткой:

Строка 15 — это элемент <hr>, который представляет собой горизонтальное правило для разделения контента.

Строка 16 — это компонент <Outlet> для рендеринга активного дочернего маршрута.

<Outlet> вызывает вложенные маршруты, где каждый маршрут может иметь дочерние маршруты, занимающие часть URL-адреса. Вложенные маршруты обычно используют относительные ссылки (строка 8 и строка 11).

Вот модифицированный src/App.js:

В строке 9 маршрут верхнего уровня — "/", и он отображает компонент MainPage. Под ним есть три дочерних маршрута:

  • Индексный маршрут (строка 10): показывает текст No page is selected.

  • Маршрут с подстановочными знаками (строка 11): показывает компонент PageOne.

  • Маршрут "two" (строка 12): показывает компонент PageTwo.

Хук useRoutes

Вместо <Routes> мы также можем использовать хук useRoutes, чтобы выполнить то же самое.

Вложенные маршруты в src/App.js можно переписать с помощью useRoutes:

В строках 6–16 мы используем ловушку useRoutes для создания объекта routes из структуры данных.

Мы должны создать AppWrapper, чтобы обернуть routes внутри <browserRouter> (строки 20–26). В противном случае мы столкнемся со следующей ошибкой:

Error: useRoutes() may be used only in the context of a component.

использованиеМестоположение

Местоположение — это объект, который представляет местоположение URL. Он основан на объекте window.location браузера.

Хук useLocation возвращает объект текущего местоположения.

В строке 7 location генерируется хуком useLocation.

Строки 8–10 определяют useEffect, который регистрирует значение местоположения, если оно изменяется.

  • Когда URL-адрес равен https://localhost:3000/, консоль регистрирует:
Current location is {pathname: '/', search: '', hash: '', state: null, key: 'default'}
  • Когда URL-адрес равен https://localhost:3000/one, консоль регистрирует:
Current location is {pathname: '/one', search: '', hash: '', state: null, key: 'f2114bru'}
  • Когда URL-адрес равен https://localhost:3000/two, консоль регистрирует:
Current location is {pathname: '/two', search: '', hash: '', state: null, key: 'if9ngy0q'}
  • Когда URL-адрес равен https://localhost:3000/anything, консоль регистрирует:
Current location is {pathname: '/anything', search: '', hash: '', state: null, key: 'default'}

Хук useParams

Чтобы сделать пример более интересным, мы вложили больше маршрутов. На MainPage кроме ссылок на "Page One" и "Page Two" есть более подробные ссылки на "P1" (пункт 1) и "P2" (пункт 2).

Вот модифицированный src/App.js:

Под путем "one" (строка 23) есть еще один дочерний маршрут с динамическим параметром ":id" (строка 25).

По пути "two" (строка 28) есть еще один дочерний маршрут с динамическим параметром ":id" (строка 30).

Вот модифицированный src/MainPage.js:

Рядом со ссылкой "Page One" добавляются ссылки P1 (путь "one/1") и P2 (путь "one/2") (строки 9–10).

Рядом со ссылкой "Page Two" добавляются ссылки P1 (путь "two/1") и P2 (путь "two/2") (строки 13–14).

Хук useParams возвращает объект пар ключ/значение динамических параметров из текущего URL. Вот модифицированный src/Pages.js с использованием хука useParams:

Поскольку хук должен использоваться в компоненте React, строки 4–14 заменяют функцию getPage на компонент BuildPage.

Строка 5 использует хук useParams для получения динамического пути id. Значение id отображается в начале содержимого (строка 10).

Строка 14 генерирует PageOne через BuildPage.

Строка 15 генерирует PageTwo через BuildPage.

Когда URL-адрес равен https://localhost:3000/one/1, консоль регистрирует:

Current location is {pathname: '/one/1', search: '', hash: '', state: null, key: 'qpdrrtyg'}

useNavigate

Хук useNavigate возвращает функцию, которую можно использовать для программной навигации. Замените два <Link>s на <button>s в src/MainPage.js:

Строка 4 возвращает хук useNavigate.

Строки 10–12 определяют кнопку "Page One", где обработчик onClick перемещается по относительному пути "one".

Строки 16–18 определяют кнопку "Page Two", где обработчик onClick перемещается по относительному пути "two".

Запустите приложение. Кнопки действуют аналогично ссылкам.

Функция navigate имеет две подписи:

  • Передайте значение To (того же типа, что и <Link to>) с необязательным вторым аргументом, { replace, state }.
  • Передайте дельта-число, чтобы войти в стек истории. Например, navigate(-1) эквивалентно нажатию кнопки «Назад».

Другие крючки

Мы показали, как использовать useLocation, useNavigate, useParams и useRoutes.

Есть и другие хуки React Router:

  • useHref: возвращает URL-адрес, который можно использовать для ссылки на указанное to местоположение даже за пределами React Router.
  • useLinkClickHandler: возвращает обработчик события клика для навигации при создании пользовательской ссылки.
  • useInRouterContext: возвращает true, если компонент визуализируется в контексте <Router>, false в противном случае.
  • useNavigationType: возвращает способ перехода пользователя на текущую страницу через Action.Pop, Action.Push или Action.Replace в стеке истории.
  • useMatch: возвращает данные соответствия о маршруте по заданному пути относительно текущего местоположения.
  • useOutlet: возвращает элемент дочернего маршрута на этом уровне иерархии маршрутов.
  • useResolvedPath: Сопоставляет pathname местоположения в заданном значении to с путем к текущему местоположению.
  • useSearchParams: используется для чтения и изменения строки запроса в URL-адресе для текущего местоположения.

Заключение

React Router 6 многофункционален и прост в использовании. Он совместим с последними версиями React. Поскольку он содержит несколько критических изменений по сравнению с версией 5, рекомендуется дождаться выпуска пакета обратной совместимости, прежде чем обновлять приложения.

Спасибо за прочтение. Я надеюсь, что это было полезно. Если вам интересно, ознакомьтесь с другими моими статьями на Medium.

Примечание. Спасибо Уриану Чангу и Джошу Брауну за то, что вместе со мной оценили React Router 6.