# SPA && ROUTING ## Предыстория Со времен зарождения современного фронтенда были попытки сделать продвинутый фронт с многостраничным интерфейсом. Технически это не представляет особой сложности, однако нет особого смысла в многостраничном интерфейсе без ссылок на эти страницы. С этим же были проблемы - при любой попытке смены адресной строки браузер упорно переходил на другую страницу, т.е. *обращался к серверу* и *сбрасывал JS, подгружая новые скрипты*. Это если страница реально существовала на сервере. Обычно же **404**. ## `#` -ссылки При переходе по ссылкам внутри страницы (используя ) браузер, очевидно, страницу не перезагружает. Этим длительное время пользовались первые **SPA** типа **gmail**. На таких сервисах роутинг, аналогичный роутингу в **express** реализуется *после* символа `#` в адресе, таким образом с точки зрения браузера все эти "переходы" по ссылкам происходят внутри одной страницы, чем и пользуется **JS**, прослушивая события изменения адреса и перерисовывая содержимое страницы. ## HTML5 **HTML5** позволяет отлавливать *любое* изменение адреса, а так же управлять историей браузера. Таким образом можно полностью просимулировать работу страниц внутри **SPA**, как будто бы они загружаются с сервера. ## Почему это называется **SPA** ? Потому что физически это *одна* страница, которая просто показывает пользователю фейковые адреса и разный **DOM**. ## Как это устроено По образу и подобию роутинга в **express**, только адрес, который сопоставляется с шаблоном приходит не из браузера на бэк, а обрабатывается в самом браузере. ## React С точки зрения **React** каждая страница - это компонент. Роутинг прописывается в декларативной форме в **JSX**. ### Установка ```bash $ npm install --save react-router-dom ``` ### Подключение ```jsx import {Router, Route, Link} from 'react-router-dom'; import createHistory from "history/createBrowserHistory"; ``` ### **JSX** ```jsx
``` - `Router` обрамляет все маршруты и обеспечивает интеграцию с **Browser History API** - `Route` принимает `props`: - `path` - шаблон адреса, как в **express** (обратите внимание на `param1` и `param2`) - `component` - класс компонента. - `exact` - нужен что бы маршрут срабатывал только при полном совпадении. ### **Компоненты** Принимают параметры шаблона адреса в `props` ```javascript class ChatPage extends Component { render() { console.log(this.props) return (
{this.props.match.params.param1}
{this.props.match.params.param2}
) } } ``` ### `Link` **Компонент** `Link` предназначен для создания ссылок. ```jsx ...go to main ``` ### `Switch` **Компонент** `Switch` выбирает **первый** подходящий маршрут, остальные игнорирует: ```jsx
``` ### `Redirect` Иногда нужно назначить перенаправление с одного адреса на другой. В таком случае поможет компонент `Redirect`: ```jsx
``` При посещении адреса `/main` будет автоматически происходить переход на `/` и работать компонент `MainPage` #### Переход на другую страницу из кода Зачастую после сохранения тех или иных форм нужно перейти на другую страницу, т. е. сменить адрес в адресной строке таким образом, что бы **React Router** это обработал согласно конфигурации маршрутов. Это можно сделать с помощью **рендеринга** компонента `Redirect` без `from`. ### Вложенные маршруты В относительно крупных проектах возникает надобность разделить разные части сайта на разные наборы маршрутов. **Например**: * `/` Главная страница * `/dashboard` Личный кабинет * **...** * `/admin` Админка * `/admin/` * `/admin/dashboard` Админский кабинет * **...** В такой структуре логично отделить маршруты общей и административной части сайта. ```jsx //App
... class AdminPage extends Component { render(){ let root = this.props.match.url return(
) } } ```