Перейти к содержимому

React router что это

  • автор:

React Router: что это и как использовать

Рассказали, что такое React Router, что такое маршрутизация, для чего она нужна и как настроить простую и вложенную маршрутизацию на сайте. Привели примеры кода.

Обложка поста React Router: что это и как использовать

Рассказали, что такое React Router, что такое маршрутизация, для чего она нужна и как настроить простую и вложенную маршрутизацию на сайте. Привели примеры кода.

  1. Что такое React Router и кому это нужно
  2. Установка React Router
  3. Создание простых маршрутов
  4. Создание вложенных маршрутов

Используете маршрутизацию?
Да, в React
Да, в Node.js
Да, но использую другой инструмент

Что такое React Router и кому это нужно

React Router – это библиотека для навигации между разными частями веб-приложения, созданными на React. Она позволяет менять содержимое страницы без перезагрузки браузера, что делает приложение более интерактивным и удобным для пользователей.

Она была разработана в 2014 году Дэном Абрамовым и Майклом Джексоном. Они заметили, что в React не хватает инструмента для удобной работы с маршрутизацией – как раз процессом переключения компонентами React. Приложения на React не могли легко менять содержимое страницы без перезагрузки, что было неудобно для пользователей и не соответствовало потребностям современных веб-приложений.

React Router решает эту проблему. Библиотека помогает создавать одностраничные приложения (SPA), где пользователь может перемещаться по разным URL, и каждый URL отображает нужный компонент без перезагрузки всей страницы.

SPA (Single Page Application) – это тип веб-приложений, которые загружают только одну HTML-страницу и динамически обновляют ее содержимое без перезагрузки страницы. Вместо того, чтобы загружать новые страницы с сервера при каждом переходе, SPA загружают только необходимые данные и обновляют содержимое на текущей странице, используя JavaScript и AJAX-запросы.

При клике на ссылку или вводе нового URL в адресной строке браузера, маршрутизация помогает приложению понять, какой компонент React нужно отобразить на экране, чтобы показать правильную информацию или функционал.

Установка React Router

В первую очередь, создайте новый проект React.

npx create-react-app my-react-app cd my-react-app 

После этого установите React Router DOM, которая работает в веб-приложениях.

npm install react-router-dom 

Создание простых маршрутов

Допустим, у вас есть два компонента: Home.js и About.js , которые вы хотите использовать для отображения на разных страницах.

Создайте эти компоненты в вашем проекте:

// Home.js import React from 'react'; function Home() < return ( 

Домашняя страница

); > export default Home;
// About.js import React from 'react'; function About() < return ( 

О нас

); > export default About;

Отредактируйте App.js , чтобы добавить маршруты для созданных вами компонентов.

import React from 'react'; import < BrowserRouter as Router, Route, Switch >from 'react-router-dom'; import Home from './Home'; import About from './About'; function App() < return (  
); > export default App;

Запустите приложение React:

npm start 

Теперь откройте браузер и перейдите по адресу ниже, чтобы открыть страницу Home .

http://localhost:3000/ 

Откройте About , чтобы увидеть страницу “О нас”.

http://localhost:3000/about 

Поздравляем, вы настроили простую маршрутизацию.

Создание вложенных маршрутов

Кроме простой маршрутизации, в React Router есть и вложенная – это использование маршрутов внутри других маршрутов. Она нужна, если у вас есть компоненты, которые сами по себе имеют свою собственную логику маршрутизации.

Давайте представим, что у вас есть веб-приложение с разными страницами: “Главная”, “О нас”, “Контакты”. Каждая из этих страниц может содержать свои собственные разделы с дополнительным контентом и функциональностью.

Вложенная маршрутизация позволяет создавать подразделы внутри этих страниц. Например, на странице “О нас” вы можете иметь свои собственные подстраницы: “История”, “Команда”, “Наши ценности”.

React Router позволяет определять маршруты для этих подстраниц внутри компонентов страниц.

Давайте представим, что у нас есть компонент Dashboard , который имеет свою собственную маршрутизацию для отображения различных частей панели управления, таких как Overview , Settings , Profile и так далее.

В компоненте Dashboard мы используем useRouteMatch из React Router, чтобы получить текущий путь и URL. Используя Link , мы создаем ссылки для перехода к разным частям панели управления. Внутри Switch мы определяем вложенные маршруты для отображения компонентов в зависимости от текущего URL.

Каждый вложенный маршрут начинается с $ , чтобы создавать правильные вложенные URL для компонентов. Это помогает React Router правильно выбирать, какой компонент отобразить на экране при совпадении URL.

В реальных приложениях структура и вложенность маршрутов может быть сложнее, но основной принцип остается тем же.

Итоги

  1. React Router – это библиотека для маршрутизации компонентов в веб-приложении;
  2. Библиотека помогает создавать одностраничные приложения (SPA), которые подгружают не всю страницу при переходе, а только нужные компоненты, чтобы ускорить сайт;
  3. Кроме простой маршрутизации, есть и вложенная. Она помогает изменять компоненты, если внутри элементов есть другие динамические элементы.
  4. Чтобы настроить маршрутизацию, используйте хуки из React Router DOM.

Простой туториал React Router v4

image

React Router v4 — это переработанный вариант популярного React дополнения. Зависимые от платформы конфигурации роутов из прошлой версии были удалены и теперь всё является простыми компонентами.

Этот туториал покрывает всё что вам нужно для создания веб-сайтов с React Router. Мы будем создавать сайт для локальной спортивной команды.

Хочешь посмотреть демку?

Установка

React Router v4 был разбит на 3 пакета:

react-router
router-dom
react-router-native

react-router предоставляет базовые функции и компоненты для работы в двух окружениях(Браузере и react-native)

Мы будем создавать сайт который будет отображаться в браузере, поэтому нам следует использовать react-router-dom . react-router-dom экспортирует из react-router все функции поэтому нам нужно установить только react-router-dom .

npm install --save react-router-dom

Router

При старте проекта вам нужно определить какой тип роутера использовать. Для браузерных проектов есть BrowserRouter и HashRouter компоненты. BrowserRouter — следует использовать когда вы обрабатываете на сервере динамические запросы, а HashRouter используйте когда у вас статический веб сайт.

Обычно предпочтительнее использовать BrowserRouter , но если ваш сайт расположен на статическом сервере(от перев. как github pages), то использовать HashRouter это хорошее решение проблемы.
Наш проект предполагает использование бекенда поэтому мы будем использовать BrowserRouter .

История — History

Каждый Router создает объект history который хранит путь к текущему location[1] и перерисовывает интерфейс сайта когда происходят какие то изменения пути.

Остальные функции предоставляемые в React Router полагаются на доступность объекта history через context, поэтому они должны рендериться внутри компонента Router.

Заметка: Компоненты React Router не имеющие в качестве предка компонент Router не будут работать, так как не будет доступен context.

Рендеринг Router

Компонент Router ожидает только один элемент в качестве дочернего. Что бы работать в рамках этого условия, удобно создать компонент который рендерить всё ваше приложение(это так же важно для серверного рендеринга).

import < BrowserRouter >from 'react-router-dom'; ReactDOM.render((   ), document.getElementById('root')) 

App компонент

Наше приложение начинается с компонента который мы разделим на две части. который будет содержать навигационные ссылки и который будет содержать контент роутов.

// Этот компонент будет отрендерен с помощью нашего const App = () => ( 
)

Routes

компонент это главный строительный блок React Router’а. В том случае если вам нужно рендерить элемент в зависимости от pathname URL’ов, то следует использовать компонент

Path — путь

принимает path в виде prop который описывает определенный путь и сопоставляется с location.pathname.

В примере выше сопоставляет location.pathname который начинается с /roster[2]. Когда текущий location.pathname сопоставляется положительно с prop path то компонент будет отрендерен, а если мы не можем их сопоставить, то Route ничего не рендерит[3].

  // Когда location.pathname это '/', prop path не совпадает // Когда location.pathname это '/roster' или '/roster/2', prop path совпадает // Если установлен exact prop. Совпадает только строгое сравнение '/roster', но не // '/roster/2' 

Заметка: Когда речь идет о пути React Router думает только о пути без домена. Это значит, что в адресе:

http://www.example.com/my-projects/one?extra=false

React Router будет видеть только /my-projects/one

Сопоставление пути

npm пакет path-to-regexp компилирует prop path в регулярное выражение и сопоставляет его против location.pathname. Строки path имеют более сложные опции форматирования чем объясняются здесь. Вы можете почитать документацию.

Когда пути сопоставляются создается объект match который содержит свойства:

  • url — сопоставляемая часть текущего location.pathname
  • path — путь в компоненте Route
  • isExact — path в Route === location.pathname
  • params — объект содержит значения из path которые возвращает модуль path-to-regexp

Заметка: path в Route должен быть абсолютным[4].

Создание наших роутов

Компонент Route может быть в любом месте в роутере, но иногда нужно определять, что рендерить в одно и тоже место. В таком случае следует использовать компонент группирования Route’ов — . итеративно проходит по дочерним компонентам и рендерит только первый который подходит под location.pathname.

У нашего веб-сайта пути которые мы хотим сопоставлять такие:

  • / — Главная страница
  • /roster — Страница команд
  • /roster/:number — Страница профиля игрока по номеру
  • /schedule — Расписание игр команды

Что делает рендер компонента Route?

У Route есть 3 props’a которые описывают каким образом выполнить рендер сопоставляя prop path с location.pathname и только один из prop должен быть представлен в Route:

  • component — React компонент. Когда роут удовлетворяется сопоставление в path, то он возвращает переданный component (используя функцию React.createElement).
  • render — функция которая должна вернуть элемент React. Будет вызвана когда удовлетворится сопоставление в path. Render довольно похож на component, но используется для inline рендеринга и подстановки необходимых для элемента props[5].
  • children — в отличие от предыдущих двух props children будет всегда отображаться независимо от того сопоставляется ли path или нет.
 /> const extraProps = < color: 'red' > ( data=/> )>/> ( props.match ? /> : /> )>/> 

В типичных ситуациях следует использовать component или render. Children prop может быть использован, но лучше ничего не делать если path не совпадает с location.pathname.

Элементу отрендеренному Route будет передано несколько props. match — объект сопоставления path с location.pathname , location объект[6] и history объект(созданный самим роутом)[7].

Main

Сейчас мы опишем основную структуру роутера. Нам просто нужно отобразить наши маршруты. Для нашего приложения мы будем использовать компонент и компонент внутри нашего компонента который поместит сгенерированный HTML удовлетворяющий сопоставлению path внутри.

import < Switch, Route >from 'react-router-dom' const Main = () => ( 
/> /> />
)

Заметка: Route для главной страницы содержит prop exact , благодаря которому пути сравниваются строго.

Унаследованные роуты

Профиль игрока /roster/:number не включен в . Вместо этого он будет рендериться компонентом который рендериться всякий раз когда путь начинается с /roster .

В компоненте Roster мы создадим компоненты для двух путей:

  • /roster — с prop exact
  • /roster/:number — этот route использует параметр пути, который будет отловлен после /roster
const Roster = () => ( /> /> ) 

Может быть полезным группирование роутов которые имеют общие компоненты, что позволяет упростить родительские маршруты и позволяет отображать контент который относиться к нескольким роутам.

К примеру может быть отрендерен с заголовком который будет отображаться во всех роутах которые начинаются с /roster .

const Roster = () => ( 

This is a roster page!

/> />
)

Параметры в path

Иногда нам требуется использовать переменные для получения какой либо информации. К примеру, роут профиля игрока, где нам требуется получить номер игрока. Мы сделали это добавив параметр в prop path .

:number часть строки в /roster/:number означает, что часть path после /roster/ будет получена в виде переменной и сохранится в match.params.number . К примеру путь /roster/6 сгенерирует следующий объект с параметрами:

Компонент будет использовать props.match.params для получения нужной информации которую следует отрендерить.

// API возращает информацию об игроке в виде объекта import PlayerAPI from './PlayerAPI' const Player = (props) => < const player = PlayerAPI.get( parseInt(props.match.params.number, 10) ) if (!player) < return 
Sorry, but the player was not found
> return (

(#)

)

Заметка: Вы можете больше изучить о параметрах в путях в пакете path-to-regexp

Наряду с компонентом наш веб-сайт использует и другие как , и .

Ссылки

Последний штрих, наш сайт нуждается в навигации между страницами. Если мы создадим обычные ссылки то страница будет перезагружаться. React Router решает эту проблему компонентом который предотвращает перезагрузку. Когда мы кликаем на он обновляет URL и React Router рендерит нужный компонент без обновления страницы.

использует prop to для описания URL куда следует перейти. Prop to может быть строкой или location объектом (который состоит из pathname, search, hash, state свойств). Если это строка то она конвертируется в location объект.

>>Player #7 

Заметка: Пути в компонентах должны быть абсолютными[4].

Работающий пример

Весь код нашего веб сайта доступен по этому адресу на codepen.

Route готов!

Надеюсь теперь вы готовы погрузиться в изучение деталей маршрутизации веб приложений.

Мы использовали самые основные компоненты которые вам понадобятся при создании собственных веб приложений ( , , and ), но есть еще несколько компонентов и props которые здесь не рассмотрены. К счастью у React Router есть прекрасная документация где вы можете найти более подробное объяснение компонентов и props. Так же в документации предоставляются работающие примеры с исходным кодом.

Пояснения

[1] — Объект location описывает разные части URL’a

// стандартный location < pathname: '/', search: '', hash: '', key: 'abc123' state: <>>

[2] — Вы можете использовать компонент без path. Это полезно для передачи методов и переменных которые храняться в context .

[3] — Если вы используете prop children то route будет отрендерен даже если path и location.pathname не совпадают.

[4] — Сейчас ведется работа над относительными путями в и . Относительные более сложные чем могут показаться, они должны быть разрешены используя свой родительский объект match , а не текущий URL.

[5] — Это stateless компонент. Внутри есть большая разница между render и component . Component использует React.createElement для создания компонента, в то время как render используется как функция. Если бы вы определили inline функцию и передали через нее props то это было бы намного медленнее чем с использованием функции render .

/> // React.createElement(props.component) >/> // props.render()

[6] — Компоненты и могут оба использовать prop location. Это позволяет сопоставлять их с path, который фактически отличается от текущего URL’а.

[7] — Так же передают staticContext , но он полезен только при рендере на сервере.

Маршрутизация

В React имеется своя система маршрутизации, которая позволяет сопоставлять запросы к приложению с определенными компонентами. Ключевым звеном в работе маршрутизации является модуль react-router, который содержит основной функционал по работе с маршрутизацией. Однако если мы собираемся работать в браузере, то нам также надо использовать модуль react-router-dom, а также history

Итак, определим в проекте следующий файл index.html :

    Маршруты в React           

Аналогичный пример с использованием классов-компонентов:

    Маршруты в React           

Прежде всего для работы с маршрутами необходимо добавить ссылки на модули react-router-dom, react-router и history:

В системе маршрутизации каждый маршрут сопоставляется с определенным компонентом, поэтому для примера я определил три однотипных компонента: Main, About и NotFound.

В начале для работы с маршрутами также получаем ряд объектов, которые потребуются для определения маршрутов:

const Router = ReactRouterDOM.BrowserRouter; const Route = ReactRouterDOM.Route; const Routes = ReactRouterDOM.Routes;

Здесь определены три объекта из модуля react-router-dom.

Router определяет набор маршрутов и, когда к приложению, приходит запрос, то Router выполняет сопоставление запроса с маршрутами. И если какой-то маршрут совпадает с URL запроса, то этот маршрут выбирается для обработки запроса.

И также для выбора маршрута определен объект Routes . Он содержит набор маршрутов и позволяет выбрать первый попавшийся маршрут и его использовать для обработки.

Каждый маршрут представляет объект Route . Он имеет ряд атрибутов. В частности, здесь для маршрута устанавливаются два атрибута:

  • path : шаблон адреса, с которым будет сопоставляться запрошенный адрес URL
  • element — тот компонент, который отвечает за обработку запроса по этому маршруту

Например, первый маршрут выступает в качестве корневого. Он сопоставляется с адресом «/» и обрабатывается компонентом Main:

Второй маршрут будет сопоставляться с адресом «/about», а обрабатываться он будет компонентом About.

Особо следует выделить третий маршрут:

Путь в виде звездочки — «*» указывает, что этот маршрут будет сопоставляться со всеми адресами URL, которые не соответствуют предыдущим маршрутам. И он будет обрабатываться компонентом NotFound. Таким образом мы можем задать обработку при обращении к несуществующим ресурсам в приложении.

При работе с маршрутами следует учитывать, что мы не сможем просто кинуть страницу index.html в браузер, и у нас все заработает, как в прошлых статьях. Чтобы система маршрутизации заработала, нам надо разместить файл index.html на веб-сервере. В качестве веб-сервера можно использовать любой понравивший веб-сервер (Apache, IIS, Ngnix и т.д.) или обращаться к данной html-странице в рамках веб-приложения. В данном же случае я буду использовать Node.js как самый демократичный и распространенный вариант.

Итак, напишем небольшое приложение Node.js для запуска html-страницы index.html. Для этого добавим в тут же папку, где находится файл index.html , новый файл app.js со следующим кодом:

const http = require("http"); const fs = require("fs"); http.createServer(function(request, response)< fs.readFile("index.html", function(error, data)< response.end(data); >); >).listen(3000, function()< console.log("Server started at 3000"); >);

В начале файла подключаются модули http (для запуска веб-сервера и обработки входящих запросов) и fs (для считывания файла index.html из файловой системы).

Далее создаем собственно веб-сервер с помощью функции http.createServer() . В качестве параметра она принимает функцию, которая будет запускаться для обработки каждого приходящего на сервер запроса. И эта функция имеет два параметра: request — объект, который хранит все данные запроса, и response — объект, который позволяет определить нам ответ на запрос.

В данном случае у нас предельно простая ситуация — нам надо просто отправить статический файл index.html . Для этого с помощью функции fs.readFile() считываем из файловой системы запрошенный файл и с помощью метода response.end() отправляем считанный данные пользователю.

И в конце функция listen() запускает созданный веб-сервер на 3000-м порту, и после этого мы сможем обращаться к приложению по адресу «http://localhost:3000».

Теперь запустим приложение. Для этого откроем командную строку/терминал и перейдем с помощью команды cd к папке проекта. Затем запустим приложение с помощью команды

node app

Маршрутизация в React и react-router и react-router-dom

После запуска сервера обратимся в браузере по адресу http://localhost:3000/ , и по умолчанию сработает маршрут «/», который обрабатывается компонентом Main:

Маршруты в React

Обратимся теперь по адресу http://localhost:3000/about :

Определение маршрутов в React

Этот запрос будет обрабатываться компонентом About, так как он отвечает за обработку маршрута, который совпадает с запросом «/about».

Запросы по всем другим адресам, которые не соответствуют предыдущим маршрутам, будут обрабатываться компонентом NotFound.

Router и Route в React

С помощью атрибута element объекта Route также можно без применения классов динамически определить содержимое компонента, который будет обрабатывать маршрут:

  > /> About> /> Contacts)> /> > />  

Сопоставление запроса с маршрутом

При определении маршрутов следует учитывать, что действует точное сопоставление с шаблоном, который указан в свойстве path элемента Route. Например, возьмем второй маршрут:

About> />

Данный маршрут соответствует запросам:

  • http://localhost:3000/about
  • http://localhost:3000/about/

Полное руководство по React Router v6. Часть 4 — Подробно о роутерах

В этой статье рассмотрим все виды роутеров из библиотеки React Router v6 — BrowserRouter, NativeRouter, HashRouter, HistoryRouter, MemoryRouter, StaticRouter.

  1. Основы React Router
  2. Продвинутые определения маршрутов
  3. Управление навигацией
  4. Подробно о роутерах (рассматривается в этой статье)

BrowserRouter

Из первой части мы уже знакомы с BrowserRouter . Это роутер по умолчанию, который вы должны использовать, если вы работаете над веб-приложением, и это роутер, который вы будете использовать в 99% всех своих приложений, поскольку он охватывает все обычные варианты использования маршрутизации. Другие роутеры, о которых поговорим далее, имеют очень специфические варианты использования.

NativeRouter

NativeRouter по сути является эквивалентом BrowserRouter , но для React Native. Если вы используете React Native, то это роутер, который вы захотите использовать.

HashRouter

Этот роутер работает очень похоже на BrowserRouter , но основное отличие заключается в том, что вместо того, чтобы изменять URL-адрес на что-то вроде http://localhost:3000/books он будет хранить URL-адрес в хэше, как http://localhost:3000/#/books . Как видите, этот URL-адрес имеет # после URL-адреса, который представляет собой хэш-часть URL-адреса. Все, что находится в хэш-части URL-адреса, является просто дополнительной информацией, которая обычно обозначает идентификатор на странице для целей прокрутки, поскольку страница будет автоматически прокручиваться до элемента с идентификатором, представленным хешем, при загрузке страницы. В React Router этот хэш на самом деле не используется для хранения идентификационной информации для прокрутки, а вместо этого он хранит информацию, связанную с текущим URL-адресом. Причина, по которой React Router делает это, заключается в том, что некоторые хостинг-провайдеры не позволяют вам фактически изменять URL-адрес вашей страницы. В этих очень редких случаях вы захотите использовать HashRouter , поскольку HashRouter не изменит фактический URL-адрес вашей страницы, а изменит только хэш вашей страницы. Если вы можете использовать какой-либо URL-адрес у своего хостинг-провайдера, то это не то, что вам следует использовать.

HistoryRouter

HistoryRouter (в настоящее время называется unstable_HistoryRouter ) — это роутер, который позволяет вручную управлять объектом истории, который React Router использует для хранения всей информации, связанной с историей маршрутизации вашего приложения. Этот объект истории помогает убедиться, что такие вещи, как кнопки «Назад» и «Вперед» в браузере, работают правильно. Это роутер, который вы, вероятно, никогда не должны использовать, если у вас нет очень конкретной причины, по которой вы хотите перезаписать или контролировать поведение истории по умолчанию React Router.

MemoryRouter

MemoryRouter немного отличается от остальных роутеров, о которых мы говорили, поскольку вместо того, чтобы хранить информацию о текущем маршруте в URL-адресе браузера, этот роутер хранит информацию о роуте непосредственно в памяти. Очевидно, что это очень неподходящий роутер для обычных операций маршрутизации, но этот роутер невероятно полезен, когда вы пишете тесты для своего приложения, у которого нет доступа к браузеру. Из-за того, как работает React Router, вам необходимо, чтобы ваши компоненты были упакованы в маршрутизатор, иначе весь ваш код маршрутизации будет выдавать ошибки и ломаться. Это означает, что даже если вы хотите протестировать один компонент, вам нужно будет обернуть этот компонент внутрь маршрутизатора, иначе он будет выдавать ошибки. Если вы тестируете свой код таким образом, что у него нет доступа к браузеру (например, модульное тестирование), то маршрутизаторы, о которых мы говорили до сих пор, будут выдавать ошибки, поскольку все они зависят от URL-адреса в браузере. MemoryRouter , с другой стороны, хранит всю свою информацию в памяти, что означает, что он никогда не обращается к браузеру и идеально подходит при модульном тестировании компонентов. Однако, за исключением этого конкретного случая использования, этот маршрутизатор никогда не будет использоваться.

StaticRouter

Роутер StaticRouter также имеет очень специфический вариант использования. Этот маршрутизатор специально предназначен для серверного рендеринга ваших приложений React, поскольку он принимает один проп location и визуализирует ваше приложение, используя этот location в качестве URL-адреса. Этот роутер на самом деле не может выполнять какую-либо маршрутизацию и будет просто отображать одну статическую страницу, но это идеально подходит для рендеринга на сервере, поскольку вы хотите просто отобразить HTML вашего приложения на сервере, а затем клиент может настроить всю вашу маршрутизацию и так далее.

Итоги

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

Полное руководство по React Router v6. Часть 3 — Управление навигацией

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *