[Перевод] Краткое руководство по React Router v4

внешний интерфейс сервер React.js регулярное выражение
[Перевод] Краткое руководство по React Router v4

«Статья была впервые опубликована вGitHub Blog

Оригинальный адрес:A Simple React Router v4 Tutorial

React Router v4 — это популярный пакет React, полностью переписанный на React, а предыдущие версии React Router были настроены на использование неизвестных псевдокомпонентов. Теперь с React Router v4 все «просто компоненты».

В этом уроке мы создадим локальную страницу «спортивные команды» и рассмотрим все основные потребности для создания нашего сайта и маршрутизации, в том числе:

  1. выберитеrouter.
  2. Создайтеroutes.
  3. Навигация по ссылкам между маршрутами.

код

Edit A Simple React Router v4 Tutorial

Установить

React Router теперь разделен на три пакета:react-router,react-router-dom,react-router-native.

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

Вы должны выбрать пакет из двух, который подходит для вашей среды разработки, нам нужно создать веб-сайт (работает в браузере), поэтому нам нужно установитьreact-router-dom

npm install --save react-router-dom

Router

Начиная новый проект, вы должны решить, какой из них использоватьrouter. Для проектов, работающих в браузере, мы можем выбрать<BrowserRouterи<HashRouter>компоненты,<BrowserRouter>Следует использовать в проектах, где сервер обрабатывает динамические запросы (умеет обрабатывать произвольные URI),<HashRouter>Используется для обработки статических страниц (отвечает только на запросы известных файлов).

Обычно рекомендуется использовать<BrowserRouter>, но если сервер обрабатывает только запросы статических страниц, используйте<HashRouter>Тоже достаточное решение.

Для нашего проекта мы предполагаем, что все страницы динамически генерируются сервером, поэтому нашrouterВыбор компонентов<BrowserRouter>.

History

каждыйrouterсоздастhistoryОбъект, используемый для отслеживания текущей позиции [1] и для повторного рендеринга страницы при ее изменении. Другие компоненты, предоставляемые React Router, зависят отcontextхранится наhistoryобъекты, поэтому они должны быть вrouterВнутренний рендеринг объектов.никто неrouterОбъекты React Router для элементов-предков не будут работать, если вы хотите узнать больше оhistoryзнание объекта, может относиться кэта статья.

оказывать<Router>

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

import { BrowserRouter } from 'react-router-dom'
ReactDOM.render((
  <BrowserRouter>
    <App />
  </BrowserRouter>
), document.getElementById('root'))

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

<App>

Наше приложение определено в<App>компонентов, чтобы упростить<App>, делим наше приложение на две части,<Header>Компоненты содержат навигацию, которая ссылается на другие страницы,<Main>Компоненты содержат остальные части, которые необходимо визуализировать.

// this component will be rendered by our <___Router>
const App = () => (
  <div>
    <Header />
    <Main />
  </div>
)

Note:Вы можете расположить свое приложение так, как хотите, а разделение маршрутов и навигации упрощает понимание того, как работает React Router.

Начнем с рендеринга содержимого маршрутизации.<Main>Компоненты запускаются.

Routes

<Route>Компоненты являются основной частью React Router. Если вы хотите отобразить что-то где угодно, когда путь совпадает, вам следует создать<Route>элемент.

Path

Один<Route>Компонент ожидает строку типаpathprop, чтобы указать путь, которому должен соответствовать маршрут. Например,<Route path='/roster/'будет соответствовать/roster[2] Начальный путь, когда текущий путь иpathПри совпадении маршрут будет отображать соответствующий элемент React. Когда путь не совпадает, маршрут не будет отображать никаких элементов [3].

<Route path='/roster'/>
// when the pathname is '/', the path does not match
// when the pathname is '/roster' or '/roster/2', the path matches
// If you only want to match '/roster', then you need to use
// the "exact" prop. The following will match '/roster', but not
// '/roster/2'.
<Route exact path='/roster'/>
// You might find yourself adding the exact prop to most routes.
// In the future (i.e. v5), the exac t prop will likely be true by
// default. For more information on that, you can check out this 
// GitHub issue:
// https://github.com/ReactTraining/react-router/issues/4958

**Примечание. **При сопоставлении маршрутов React Router заботится только об относительной части пути, поэтому следующий URL-адрес

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

React Router только попытается сопоставить/my-projects/one.

путь совпадения

React Router используетpath-to-regexpпакет для определения путиpathесли реквизит соответствует текущему пути, он будетpathСтрока преобразуется в регулярное выражение для соответствия текущему пути, примерноpathДополнительные необязательные форматы строк см.path-to-regexp Документация.

Когда маршрут совпадает с путем,matchОбъект будет передан в качестве реквизита

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

**Примечание: **В настоящее время путь маршрута должен быть абсолютным путем [4].

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

<Route>s можно создавать в любом месте роутера, но вообще логичнее их рендерить там же, можно использовать<Switch>компоненты для объединения<Route>Да,<Switch>пройдет через егоchildrenэлемент (маршрут), то только первый соответствующийpathname.

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

  1. /- Домашняя страница
  2. /roster- Список команд
  3. /roster/:number- Информация об игроке с использованием номера футболки игрока, чтобы отличить
  4. /schedule- Расписание команды

Чтобы соответствовать пути, нам нужно создать бэндpathопора<Route>элемент

<Switch>
  <Route exact path='/' component={Home}/>
  {/* both /roster and /roster/:number begin with /roster */}
  <Route path='/roster' component={Roster}/>
  <Route path='/schedule' component={Schedule}/>
</Switch>

<Route>что будет визуализировано

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

  1. <component>- компонент React, когда он сcomponentКогда маршрут реквизита совпадает, маршрут вернет компонент типа component, предоставленный реквизитом (черезReact.createElementрендеринг).
  2. render— метод, возвращающий элемент React [5], сcomponentТочно так же он вызывается при совпадении пути. Это очень удобно при написании встроенной формы для рендеринга и передачи параметров.
  3. children- Метод, возвращающий элемент React. В отличие от первых двух, этот методвсегдабудет отображаться независимо от того, соответствует ли маршрут текущему пути.
<Route path='/page' component={Page} />
const extraProps = { color: 'red' }
<Route path='/page' render={(props) => (
  <Page {...props} data={extraProps}/>
)}/>
<Route path='/page' children={(props) => (
  props.match
    ? <Page {...props}/>
    : <EmptyPage {...props}/>
)}/>

В общем, мы обычно используемcomponentилиrender,childrenСуществует не так много вариантов использования, и, как правило, лучше ничего не отображать, когда маршруты не совпадают. В нашем случае нам не нужно передавать какие-либо параметры маршруту, поэтому мы используем<component>.

Зависит от<Route>Визуализированный элемент будет иметь набор реквизитов, в том числеmatchобъект, текущийlocationОбъект [6] иhistoryОбъект (созданный маршрутизатором) [7].

<Main>

Теперь, когда мы определили структуру маршрутов, нам осталось их реализовать. В нашем приложении мы будем<Main>Рендеринг в компоненте<Switch>и<Route>, они будут в<main>Визуализация HTML-элементов в формате .

import { Switch, Route } from 'react-router-dom'
const Main = () => (
  <main>
    <Switch>
      <Route exact path='/' component={Home}/>
      <Route path='/roster' component={Roster}/>
      <Route path='/schedule' component={Schedule}/>
    </Switch>
  </main>
)

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

вложенность маршрутов

Маршрутизация страниц профиля игрока/roster/:numberв<Roster>компоненты, не входящие в<Switch>середина. Однако, пока имя пути указано/rosterначни, будет<Roster>Рендеринг компонентов.

существует<Roster>В компоненте мы будем отображать два пути:

  1. /roster- только если путь точно совпадает/rosterбудет отображаться, когда мы захотим указать путьexactпараметр.
  2. /roster/:number- этот маршрут использует параметр пути для захвата/rosterЧасть имени пути, за которой следует.
const Roster = () => (
  <Switch>
    <Route exact path='/roster' component={FullRoster}/>
    <Route path='/roster/:number' component={Player}/>
  </Switch>
)

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

Например,<Roster>доступно для всех/rosterМаршрут в начале отображает заголовок

const Roster = () => (
  <div>
    <h2>This is a roster page!</h2>
    <Switch>
      <Route exact path='/roster' component={FullRoster}/>
      <Route path='/roster/:number' component={Player}/>
    </Switch>
  </div>
)

Параметр пути

Иногда нам нужно захватить несколько параметров в имени пути, например, в маршрутизации нашего профиля игрока мы можем перейти к путиpathДобавлен параметр пути для захвата номера игрока.

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

{ number: '6' } // note that the captured value is a string

<Player>Использование компонентовprops.match.paramsобъект, чтобы решить, какие данные игрока должны быть отображены.

// an API that returns a player object
import PlayerAPI from './PlayerAPI'
const Player = (props) => {
  const player = PlayerAPI.get(
    parseInt(props.match.params.number, 10)
  )
  if (!player) {
    return <div>Sorry, but the player was not found</div>
  }
  return (
    <div>
      <h1>{player.name} (#{player.number})</h1>
      <h2>{player.position}</h2>
    </div>
)

оpathС параметрами можно ознакомитьсяpath-to-regexp Документация.

прямо рядом с<Player>, есть еще один<FullRoster>,<Schedule>и<Home>компоненты.

const FullRoster = () => (
  <div>
    <ul>
      {
        PlayerAPI.all().map(p => (
          <li key={p.number}>
            <Link to={`/roster/${p.number}`}>{p.name}</Link>
          </li>
        ))
      }
    </ul>
  </div>
)
const Schedule = () => (
  <div>
    <ul>
      <li>6/5 @ Evergreens</li>
      <li>6/8 vs Kickers</li>
      <li>6/14 @ United</li>
    </ul>
  </div>
)
const Home = () => (
  <div>
    <h1>Welcome to the Tornadoes Website!</h1>
  </div>
)

Links

Наконец, нашему веб-сайту необходимо перемещаться между страницами, если мы используем<a>Навигация с вкладками загрузит совершенно новую страницу. React Router предоставляет<Link>компонент, чтобы избежать этого при нажатии<Link>, URL-адрес будет обновлен, и страница будет отображать содержимое без загрузки всей новой страницы.

import { Link } from 'react-router-dom'
const Header = () => (
  <header>
    <nav>
      <ul>
        <li><Link to='/'>Home</Link></li>
        <li><Link to='/roster'>Roster</Link></li>
        <li><Link to='/schedule'>Schedule</Link></li>
      </ul>
    </nav>
  </header>
)

<Link>использованиеtoprop для определения цели навигации, которая может быть строкой или объектом местоположения (содержащимpathname, search, hashиstateАтрибуты). Когда просто строка, она будет преобразована в объект местоположения

<Link to={{ pathname: '/roster/7' }}>Player #7</Link>

**Примечание: **В настоящее время путь ссылки должен быть абсолютным путем.

пример

Два онлайн-примера:

  1. CodeSandbox
  2. CodePen.

Примечания!

[1] location — это объект, содержащий параметры, описывающие различные части URL-адреса.

// a basic location object
{ pathname: '/', search: '', hash: '', key: 'abc123' state: {} }

[2] может быть бездорожьем<Route>, этот маршрут будет соответствовать всем путям, поэтому к нему можно будет легко получить доступ, хранящийся вcontextобъекты и методы на .

[3] При использованииchildrenprop, он будет отображаться, даже если путь не совпадает.

[4] пусть<Route>песок<Link>s Работа по принятию относительного пути не завершена, относительный<Link>s более сложны, чем кажутся, потому что они требуют родительского компонентаmatchобъект для работы вместо текущего URL.

[5] Это базовый компонент без гражданства,componentиrenderРазница в том,componentБудет использоватьсяReact.createElementсоздать элемент,renderИспользуется для обработки компонента как функции. Если вы хотите создать встроенную функцию и передать ее вcomponent,Такrenderбыло бы лучше, чемcomponentПриходит намного быстрее.

<Route path='/one' component={One}/>
// React.createElement(props.component)
<Route path='/two' render={() => <Two />}/>
// props.render()

[6] <Route>и<Switch>компоненты могут приниматьlocationprop, что позволяет сопоставлять их с другим местоположением, а не только с их фактическим местоположением (текущий URL-адрес).

[7] props также можно передаватьstaticContextЭто свойство работает только при использовании рендеринга на стороне сервера.