ОБНОВЛЕНИЕ 2018: в учебнике хорошая теория, но ему уже два года. Проверяйте версии пакетов. За выходом нового учебника можно следить в telegram канале или twitter
На канале так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы, присоединяйтесь!
Дописываем роуты
Пока я писал этот курс, вышел react 15, давайте обновим сразу react и react-dom.
Далее в курсе будут использованы следующие версии:
"react": "^15.0.1","react-dom": "^15.0.1",
Давайте вспомним, какие роуты мы хотели сделать:
/ - главная страница
/list - список жанров
/genre/:genre/ - список релизов данного жанра
/genre/:genre/:release - информация о релизе
/admin - страница администратора
Каждый раз, задача будет примерно такой:
нужно создать компонент (и рендерить в нем детей, если есть дочерние url'ы)
добавить компонент, как новый Route
Начнем с простого - роут, не имеющий детей - /list
P.S. в данный момент у нас не поддерживается hot-reload для роутинга. Поэтому придется обновлять браузер по старинке.
Будьте внимательны, я специально привожу не полный код, чтобы вы не страдали copy-paste.
<List /> - дочерний компонент <App />, (посмотрите на URL - / + list = две части, в переводе на react-router, это <App /> + this.props.children, и конкретно в нашем случае это <App /> + <List />)
Проверим в браузере:
Обратите внимание, что у <App /> - childRoues: Array[3], именно этими детьми и являются <Admin />, <Genre /> и <List /> в данный момент. То есть, снова никакой магии.
Так же, обратите внимание сколько свойств "прокидывает" react-router. Это нам еще пригодится.
Кстати, если сейчас кликнуть по ссылке, например House, что отобразит браузер?
Ответ - отобразится компонент <NotFound />.
Покликав на ссылки, у нас вырисовываются следующие адреса:
Для всех этих адресов, требуется отрисовывать один и тот же компонент, который будет отображать список релизов данного жанра. Как быть? Пора познакомиться с динамическим адресом.
Динамический роут
Все очень просто. Сразу к делу. Изменим в src/index.js:
<Routepath='genre'component={Genre} />
на
<Routepath='genre/:genre'component={Genre} />
Обновите браузер:
Отображается компонент <Genre />, при этом в props появилось свойство params, давайте сразу возьмем его в оборот:
src/components/Genre.js
import React, { Component } from'react'exportdefaultclassGenreextendsComponent {render() {return ( <divclassName='row'> <h3className='col-md-12'>{this.props.params.genre}</h3> <divclassName='col-md-12'>Здесь будет список релизов</div> </div> ) }}
Если попробовать ввести вместо house другое слово - все так же будет работать.
Будем называть динамическую часть url'a - параметром. То есть :genre - параметр.
Нет никакого ограничения на количество параметров в адресе. Например:
import React, { Component } from'react'exportdefaultclassReleaseextendsComponent {render() { {/* замени все '-' в параметре (то есть в адресе) на пробелы */}constreleaseName=this.props.params.release.replace(/-/g,' ');return ( <divclassName='col-md-12'> {releaseName} </div> ) }}
С параметром мы можем работать как с любым другим свойством.
Оформление routes
Чем глубже уровень вложение в роутах, тем сложнее сразу понять какому роуту соответствует тот или иной компонент. Поэтому, мы можем указать путь полностью:
Так как routes - реакт компонент, и мы используем <NotFound /> не в качестве дочернего компонента (чтобы не было "шапки"), нам пришлось обернуть роуты в <div>. Вы можете сделать иначе, если хотите, чтобы шапка (сейчас это ссылки Admin и Genre) была на всех страницах, включая 404.
У нас появилась нерабочая ссылка в шапке - Genre. Так как она нам больше не нужна, давайте заменим ее на 'Список жанров' и будем отображать компонент <List /> по клику на эту ссылку.
Заодно переименуем Admin. Удалим заголовок App и накинем парочку bootstrap классов тэгу <ul>.