Эта статья переведена с:An Introduction to React Router v4 and its Philosophy Toward Routing
Адрес перевода:GitHub.com/so coder/no...
Эта статья переведена с:An Introduction to React Router v4 and its Philosophy Toward Routing
React Router 4 представляет динамическую маршрутизацию на основе компонентов.
В этом посте мы обсудим философию, лежащую в основе размышлений о React Router, а также представим его синтаксис, проанализировав пример кода в документации React Router.
Чтобы узнать больше о React Router, нажмитездесь.
Если вы не хотите видеть текстовую версию, вы можете нажатьздесьСмотреть видео.
Если вы внимательно следили за React в течение последних нескольких лет, вы должны были заметить, что React Router претерпел несколько итераций. Сегодняшний выпуск v4 — это огромное изменение.
Причины этих изменений вполне естественны — сегодня разработчики React более опытны, чем когда React Router был впервые создан. В 2014 году все были новичками. Никто и подумать не мог, что концепция компонентов станет настолько важной менее чем за год существования React.
По вышеуказанным причинам первый коммит React Router выглядит так:
В то время у авторов React Router Майкла и Райана былиEmberопыт разработки. Естественно, первая версия React Router была чем-то похожа на маршрутизацию Ember — она строилась статически как часть инициализации приложения.
Эта концепция маршрутизации согласуется со знакомыми концепциями Express, Angular и Ember. Еще до выпуска React Router 4 использовалась статическая маршрутизация.
При использовании статической маршрутизации часто имеется такой фрагмент кода, написанный наroutes.jsв:
const routes = (
<Router>
<Route path='/' component={Main}>
<IndexRoute component={Home} />
<Route path='playerOne' component={Prompt} />
<Route path='playerTwo/:playerOne' component={Prompt} />
<Route path='battle' component={ConfirmBattle} />
<Route path='results' component={Results} />
<Route onEnter={checkAuth} path='dashboard' component={Dashboard} />
</Route>
</Router>
)
export default routes
Затем, когда приложение инициализируется, маршрут будет импортирован, а затем отрендерен:
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import routes from './config/routes'
ReactDOM.render(routes, document.getElementById('app'))
Возникает вопрос: плоха ли статическая маршрутизация?
Ответ, кажется, "Нет, это работает". Но люди по-прежнему считают, что шаблон статической маршрутизации не соответствует стилю React.
С момента рождения React Router его авторы не только приобрели больше опыта в построении маршрутизации для сложных приложений, но и лучше поняли сам React. Позже в ходе работы и обсуждения я обнаружил, что API React Router и некоторые принципы, лежащие в основе React, немного противоречат друг другу. Вернувшись назад и взглянув на предыдущий код, мы поместилиonEnterСвойство передается компоненту Route.
<Route onEnter={checkAuth} path='dashboard' component={Dashboard} />
Этот код указывает на необходимость прохождения уровня аутентификации при отображении компонента информационной панели. Похоже, это на приборной панелиcomponentDidMountДелать что-то в жизненном цикле? В самом деле.
До React Router 4 он делал что-то большее, чем маршрутизация. React Router 4 устраняет эти проблемы и улучшает работу с React. React Router 4 будет чувствовать себя более комфортно, если вы понимаете React и его преимущества использования компонентов — сначала вам нужно забыть некоторые из ваших знаний о традиционной статической маршрутизации.
Теперь возникает вопрос: что именно делает React Router 4, чтобы предотвратить конфликт с React? Ответ в том, что он отказался от статической маршрутизации и стал предпочитать динамическую маршрутизацию.Все API основаны наcomponent. Это также означает, что маршруты объявляются точно так же, как обычные компоненты.
Просто посмотрите на следующий пример:
Начните с самого простого кода, а затем добавьте к нему функции маршрутизации.
import React, { Component } from 'react'
class App extends Component {
render() {
return (
<div>
React Rotuer Course
</div>
)
}
}
export default App
Как я уже говорил, React Router 4 — обычный компонент. Итак, первое, что нужно сделать, это импортировать то, что нам нужно.
import {
BrowserRouter as Router,
Route,
Link,
} from 'react-router-dom'
Здесь следует отметить несколько вещей. Во-первых, мы импортируемBrowserRouterи переименовать его вRouter. Это не обязательно, но часто встречается в коде.BrowerRouterВсе, что он делает, это позволяет React Router передавать информацию о маршрутизации приложения любому компоненту, который ему нужен (черезcontext). Итак, для правильной работы React Router его необходимо отрендерить в корневом узле приложения.BrowerRouter.
import React, { Component } from 'react'
import {
BrowserRouter as Router,
Route,
Link,
} from 'react-router-dom'
class App extends Component {
render() {
return (
<Router>
<div>
React Rotuer Course
</div>
</Router>
)
}
}
export default App
будет использоваться дальшеRoute.RouteЯвляется основой React Router 4. Когда местоположение приложения совпадает с маршрутом,Routeотобразит указанный компонент, иначе отобразитnull. Например, когда применяемый нами маршрут/сделатьHomeкомпонент, код будет выглядеть так:
import React, { Component } from 'react'
import {
BrowserRouter as Router,
Route,
Link,
} from 'react-router-dom'
const Home = () => (
<h2>Home</h2>
)
class App extends Component {
render() {
return (
<Router>
<div>
<Route path='/' component={Home} />
</div>
</Router>
)
}
}
export default App
В приведенном выше коде, если наш путь/когда ты увидишьHomeкомпоненты. Если нет, ничего не видно (Route будет отображатьnull).
Дополнительные маршруты будут добавлены ниже:
import React, { Component } from 'react'
import {
BrowserRouter as Router,
Route,
Link,
} from 'react-router-dom'
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
const About = () => (
<div>
<h2>About</h2>
</div>
)
const Topics = () => (
<div>
<h2>Topics</h2>
</div>
)
class App extends Component {
render() {
return (
<Router>
<div>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/topics' component={Topics} />
</div>
</Router>
)
}
}
export default App
Как и выше, если вы хотите добавить больше маршрутов в свое приложение, вам просто нужно отобразить больше маршрутов.Routeкомпоненты. Если вы не забыли о статической маршрутизации, может быть странно делать такие вещи, как маршрутизация рендеринга.
ты просто должен помнитьRouteПросто обычный компонент React с методом рендеринга, который визуализирует компонент илиnullЗависит от того, совпадает ли путь. Потому что в приведенном выше примере либо рендерить компонент, либо рендеритьnull.
В приведенном выше коде следует отметить один момент: при запуске этой программы перейдите кaboutдорожка,Aboutкомпоненты иHomeКомпоненты визуализируются. Это потому, что даже/не является точным совпадением, но по-прежнему считается частичным совпадением, поэтомуHomeКомпоненты также визуализируются. Для решения этой проблемы необходимо/изRouteдобавитьexactprop, чтобы гарантировать, что будет отображаться только точное совпадение.
<Route exact path='/' component={Home} />
Теперь, когда мы динамически отображаем пользовательский интерфейс через местоположение приложения, следующим делом является изменение местоположения приложения. это точноLinkЧто делает компонент, так это компонент, который позволяет пользователю декларативно просматривать приложение. Теперь используйтеLinkДобавьте простую панель навигации.
render() {
return (
<Router>
<div>
<ul>
<li><Link to='/'>Home</Link></li>
<li><Link to='/about'>About</Link></li>
<li><Link to='/topics'>Topics</Link></li>
</ul>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/topics' component={Topics} />
</div>
</Router>
)
}
Фактически, основные операции React Router 4 были представлены. Наше использование местоположения на основе приложенийRouteдля рендеринга различных компонентов и передачиLinkкомпонент для изменения местоположения приложения.
Немного углубившись, давайте взглянем на вложенные маршруты. Вложенные маршруты были основополагающей функцией предыдущих версий React Router, и они остаются такими и сегодня. Самая большая разница по сравнению с предыдущими версиями заключается в том, как теперь создаются вложенные маршруты. В предыдущих версиях нужно было использовать только маршруты, вложенные в конфигурацию маршрутизации, но сегодня React Router 4 — это динамическая маршрутизация, так что это не сработает. Но насколько мне известно, вложенные маршруты React Router 4 более просты, чем в предыдущих версиях. Еще раз: забудьте все, что вы знали о статической маршрутизации раньше.
Снова взглянем на наш пример, если мы хотимTopicsКак насчет компонента, отображающего вложенную навигацию и некоторую другую маршрутизацию? Не нужно усложнять, например, вложениеdivНапример, вам просто нужно вложить, используяRoute.
const Topic = () => {
<div>
<h3>TOPIC</h3>
</div>
}
const Topics = () => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`/topics/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`/topics/components`}>
Components
</Link>
</li>
<li>
<Link to={`/topics/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`/topics/rendering`} component={Topic} />
<Route path={`/topics/components`} component={Topic} />
<Route path={`/topics/props-v-state`} component={Topic} />
</div>
)
Теперь, когда пользователь переходит к/topics, вы увидите вложенную панель навигации, и пользовательский интерфейс автоматически изменится при изменении местоположения. Единственная разница в том, что теперь мы рендерим внутри компонента через React Router.navbarа такжеRoute
Вы можете заметить, что мы все жестко кодируем URL-адрес, а не создаем его динамически из текущей вложенной позиции. Когда React Router визуализирует компонент, он передает три вещи:match,locationа такжеhistory. В этом примере мы хотимmatch.url, что даст нам совпадающую часть текущего URL (в нашем случае/,/topics). Так что ни в коем случае мы не жестко закодированы/topicможно использовать где угодноmatch.urlзаменять.
const Topic = () => {
<div>
<h3>TOPIC</h3>
</div>
}
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/rendering`} component={Topic} />
<Route path={`${match.url}/components`} component={Topic} />
<Route path={`${match.url}/props-v-state`} component={Topic} />
</div>
)
Вы могли заметить еще одну вещь: даже при рендеринге одного и того же компонента мы рендерим три разных компонента.Route, единственная разница между ними заключалась во вложенном URL-адресе. Вот классический пример использования параметра url.
const Topics = ({ match }) => (
<div>
...
<Route path={`${match.url}/:topicId`} component={Topic} />
</div>
)
Рендеринг React RouterTopicкомпонент, используя ранее представленныйmatchсвойства, аналогично, вы также можете использоватьmatch.paramsвнизtopicId.
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
Наконец, когда мы в/topicsПри маршрутизации, если тема не выбрана, мы хотим отобразить текст, например: Пожалуйста, выберите тему. Мы можем создать компонент, который отображает текст или использоватьRouteизrenderАтрибуты:
<Route
exact
path={match.url}
render={() => ( <h3>Please select a topic.</h3> )}
/>
Просто так наш классный код будет выглядеть так:
import React, { Component } from 'react'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
const About = () => (
<div>
<h2>About</h2>
</div>
)
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic}/>
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
)
class App extends Component {
render() {
return (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
)
}
}
export default App
React Router — этоcomponentRouter for API — это настоящий React Router. Я верю, что React сделает вас лучшим разработчиком JavaScript, а React Router 4 сделает вас лучшим разработчиком React.
Хотите пообщаться с автором? нажмитеПосмотреть исходный текст здесьпонять больше