React Router
Last updated
Was this helpful?
Last updated
Was this helpful?
Отличающее преимущество веб-приложения от десктоп это наличие URL, при переходе по которому, пользователь оказывается в определенной части приложения. Так можно сохранить закладку или передать ссылку другому пользователю, при этом ему будет отображен один и тот же интерфейс (за исключением приватных данных).
Маршрутизация (routing) - это не побочный эффект при написании приложения, наоборот, грамотную архитектуру навигации необходимо продумывать в первую очередь.
Аналогией URL-строки может быть адрес по которому вы проживаете: улица, дом, квартира. У каждого состояния интерфейса должен быть свой адрес, свой URL. То, что видит пользователь, состояние интерфейса, должно быть описано в URL.
https://
- протокол
mysite.com/
- хост
books/e3q76gm9lzk
- путь, то где мы находимся в приложении
e3q76gm9lzk
- url-параметр. Параметры бывают динамическими или статическими
?
- символ начала строки запроса
?category=adventure&status=unread
- строка запроса
category=adventure
- пара параметр=значение
&
- символ "И", разделяет параметры строки запроса
#comments
- якорь (хеш), определяет положение на странице
История навигации - то как мы переходим ссылкам, как переходы хранятся и парсятся. От типа истории зависит метод ее хранения и изменения.
Существует несколько типов истории.
Browser history - использует HTML5 History API, стандарт управления историей браузера из JavaScript.
Hash history - в старых браузерах не поддерживается HTML5 History API, поэтому для них существует эта реализация.
Memory history - позволяет использовать историю сессии в памяти, вне окна браузера. К примеру для тестирования логики без интерфейса и в средах без DOM, к примеру React Native.
Предоставляет набор компонентов для управления частями URL-строки и отображения различных компонетов в зависимости от текущего ее состояния. Разбит на пакеты для различных платформ, нас интересует react-router-dom
.
В React Router есть три типа компонентов: компонент маршрутизатора, компоненты согласования маршрутов и компоненты навигации.
В основе каждого одностраничного приложения стоит маршрутизатор. Компонент <BrowserRouter>
создает раутер и объект history
, чтобы синхронизировать интерфейс с URL-адресом. Используя контекст, передает данные о текущем URL всему поддереву компонентов.
Компонент позволяющий связать определенный URL и компонент для рендера. Его задача заключается в том, чтобы отобразить некоторый интерфес, когда location.pathname
соответствует значению пропа path
. Компонент <Route>
можно использовать в любом месте где необходимо рендерить контент на основе текущего URL.
Согласование маршрута выполняется путем сопоставления пропа path
и текущего значения location.pathname
. Если значение location.pathname
начинается на указанный путь в path
, <Route>
отрендерит указанный компонент, в противном случае вернет null
.
Когда location.pathname
начинается на '/about'
, первый и третий рауты отрендерят null
, а второй отрендерит компонент <About>
.
Проп exact
указывает на необходимость точного совпадения path
и location.pathname
<Route>
без указанного path
всегда рендерит компонент
Используется когда компонент необходимо отрендерить без передачи дополнительных пропсов. Стандартные пропсы match
, location
и history
будут переданы компоненту автоматически.
Для создания компонента используется React.createElement()
, это означает, что если вместо ссылки на компонент будет передана анонимная функция, для каждого ре-рендера будет создан новый компонент. Это приведет к размонтированию существующего компонента, созданию и монтированию нового на каждом рендере, вместо обновления существующего компонента.
Позволяет использовать инлайн-функцию вместо компонента без нежелательного эффекта ре-рендера как в случае с component
. Используется тогда, когда компоненту необходимо передать дополнительные пропсы, кроме тех что передает <Route>
.
Группирует и отображает первый дочерний маршрут, path
которого соответствует текущему location.pathname
, игнорруя все последующие.
Позволяет декларативно отрендерить компонент который во время маунта перенаправит пользователя по указанному маршруту. Под капотом использует императивный интерфейс history
.
По умолчанию подменяет текущую запись в истории, для того чтобы добавить новую запись на верх стека можно передать проп push
.
Вместо строки, проп to
может принимать полноценный объект формата location
.
Для создания навигации нельзя использовать обычный HTML-тег <a href="/about">
. При клике, вместо того чтобы изменить URL на текущей странице, и позволить раутеру выполнить навигацию на стороне клиента, браузер выполнит GET-запрос и обновит страницу, а это не то, что нам нужно.
Компоненты <Link>
и <NavLink>
используются для создания ссылок. Они рендерят HTML-тег <a>
, но с расширенным функционалом клика, используя возможности объекта history
по замене URL.
Проп to
можно передавать в виде строки описывающей href
будущей ссылки, или как объект location
со следующими (необязательными) свойствами:
pathname
- строка, путь для ссылки.
search
- строковое представление параметров запроса.
hash
- хэш для добавления в конец URL.
state
- объект, который будет записан в location.state
после перехода по ссылке.
Компонент <NavLink>
отличается от <Link>
только тем, что может иметь дополнительные стили, если текущий URL совпадает со значением пропа to
.
activeClassName
- строка классов для объеденения с className
когда элемент активен.
activeStyle
- объект инлайн стилей для добавления к элементу когда он активен.
exact
- когда true
, активные классы/стили будут применяться только в том случае, если местоположение точно совпадает со значением пропа to
.
Компоненту отрендеренному через <Route>
будет передано несколько специальных пропсов хранящих много полезной информации.
match
— объект с информацией о том как совпали path
и location.pathname
location
- объект хранящий информацию о текущем URL
history
- объект истории, созданный самим раутером
Объект, хранит информацию о том, как path
совпал с location.pathname
. Содержит следующие свойства.
params
- объект пар ключ:значение
, соответствующих динамическим параметрам URL.
isExact
- указыват на точное соотвествие path
и location.pathname
.
path
- паттерн пути на который замачился <Route>
. Используется для создания вложенных маршрутов.
url
- совпавшая часть URL-адреса. Используется для создания вложенной навигации.
Объект, свойства которого описывают текущее местоположение, путь куда будет произведен переход или откуда пришли на текущий маршрут. Можно использовать в том числе для проверки в componentDidUpdate
изменился ли текущий URL.
Объект истории со свойствами и методами для программной навигации. Используется для перенаправлений.
history.push(path [, state])
- добавляет новую запись на стек записей истории.
history.replace(path [, state])
- подменяет текущую запись на новую на стеке записей истории.
В строке запроса можно указывать дополнительную информацию о текущем маршруте. Например, если мы просматриваем страницу новостных статей, маршрут может выглядеть так.
Если есть категории выбора статей по жанру и времени издания, храним выбранные опции в строке запроса.
Строка запроса содержит 2 параметра: название категории и порядок сортировки статей. При переходе по такому маршруту, можно сделать HTTP-запрос на бэкенд, получив только статьи необходимой категории, и отсортировать их по полю даты издания.
Текущее значение строки запроса хранится в пропе location
.
Допустим, для выбора категории статей используется <select>
. При выборе опции необходимо обновлять URL используя метод history.push()
для добавления новой записи в журнал истории.
Берем текущее значение location.pathname
и обновляем search
.
Если меняется строка запроса, компоненту пробрасываются новые пропсы, и в методе componentDidUpdate()
можно проверить изменилась ли категория и порядок сортировки. Если изменились, делаем HTTP-запрос или сортируем текущие статьи.
Перенаправления это удобный инструмент навигации пользователя между маршрутами приложения. Для их реализации используется компонент <Redirect>
или методы history.push()
и history.replace()
.
Важно знать раличие методов push
и replace
.
history.push()
- добавит новую запись в журнал истории, пользователь может вернуться на тот маршрут с которого пришел.
history.replace()
- перезапишет текущую запись в журнале истории затерев текущую, пользователь не сможет вернутся на маршрут с которого пришел.
Продолжим работать со статьями. При рендере раута /articles
есть категории статей, но при первом рендере маршрута еще нет строки запроса с параметром category
. Именно поэтому необходимо сделать редирект, при этом перезаписав текущую страницу истории, чтобы пользователь не мог вернуться на страницу без параметров запроса.
Позволяет передавать кастомные данные между маршрутами. Например список статей это ссылки, при клике в ссылку переходим на новый маршрут - страницу статьи.
Тогда, если пользователь пришел с https://app.com/articles?category=sports
, и захочет вернуться на сраницу всех статей, нажав стрелку "Обратно", он попадет куда надо. Но что если необходимо реализовать кнопку "Обратно к статьям" в интерфейсе приложения, как узнать откуда мы пришли?
Каждую статью сделаем ссылкой, добавив в свойство state
информацию о текущем маршруте.
Тогда в компоненте статьи можем получить эту информацию и при клике на кнопку "Обратно к статьям" перенаправить пользователя на предыдущий маршрут.
Нужно учитывать ситуацию когда пользователь перешел на страницу статьи по сохраненный ссылке, и в текущей сессии не был на странице всех статей. В свойстве location.state
не будет объекта, и попытка доступа к state.from
приведет к ошибке выполнения скрипта.
Поэтому необходимо проверить location.state
. Если state
есть - перенаправляем пользователя туда, откуда он пришел. Если state
нет - перенаправляем на /articles
, при этом параметр category
назначаем по свойству статьи (если в объекте статьи есть такое свойство).
Если вы хотите понять React Router, рекомендуется ознакомиться с . Более конкретно, c пакетом , который предоставляет основные функциональные возможности для , позволяя одностраничным приложениям легко добавлять навигацию на стороне клиента.
Чтобы получить значения параметров, можно использовать возможности нативного класса , а также библиотеки или . Любой метод позволит сделать парс строки запроса и получить объект с парами ключ:значение
.