Первоначально это было опубликовано в Tylermcginnis.com и является частью их React Router курс.
React Router v4 представил новый декларативный подход, основанный на компонентах, к маршрутизации. С таким подходом возникла некоторая путаница вокруг вложенных маршрутов. В этом посте мы разберем эту путаницу, и вы узнаете, как гнездясь о маршрутах с помощью React Router.
видео
Почта
Чтобы понять рекурсию, вам сначала нужно быть знакомы с функциями, возвратными значениями и Callstack. Подобно, чтобы понять вложенные маршруты, вам сначала нужно чувствовать себя комфортно с самым фундаментальным компонентом React Router, <Маршрут>
Анкет
<Маршрут>
принимает дорожка
и составная часть
. Когда текущее местоположение вашего приложения соответствует дорожка
, компонент
будет отображаться. Когда это не так, Маршрут
будет рендерить NULL.
Как мне нравится думать, когда вы используете
, это всегда что -то будет делать. Если местоположение приложения соответствует Путь
, это сделает компонент
Анкет Если это не так, это будет отображаться NULL
Анкет
Я понимаю, что мы начинаем медленно здесь, но если вы полностью поймете этот последний абзац, остальная часть этого учебника будет 🍰.
С этим, давайте посмотрим на пример, который мы создадим. Идея в том, что у нас есть список тем, эти темы имеют ресурсы, и эти ресурсы имеют URL. Вот структура данных, с которой мы работаем.
const topics = [ { name: 'React Router', id: 'react-router', description: 'Declarative, component based routing for React', resources: [ { name: 'URL Parameters', id: 'url-parameters', description: "URL parameters are parameters whose values are set dynamically in a page's URL. This allows a route to render the same component while passing that component the dynamic portion of the URL so it can change based off of it.", url: 'https://tylermcginnis.com/react-router-url-parameters' }, { name: 'Programatically navigate', id: 'programmatically-navigate', description: "When building an app with React Router, eventually you'll run into the question of navigating programmatically. The goal of this post is to break down the correct approaches to programmatically navigating with React Router.", url: 'https://tylermcginnis.com/react-router-programmatically-navigate/' } ] }, { name: 'React.js', id: 'reactjs', description: 'A JavaScript library for building user interfaces', resources: [ { name: 'React Lifecycle Events', id: 'react-lifecycle', description: "React Lifecycle events allow you to tie into specific phases of a component's life cycle", url: 'https://tylermcginnis.com/an-introduction-to-life-cycle-events-in-react-js/' }, { name: 'React AHA Moments', id: 'react-aha', description: "A collection of 'Aha' moments while learning React.", url: 'https://tylermcginnis.com/react-aha-moments/' } ] }, { name: 'Functional Programming', id: 'functional-programming', description: 'In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.', resources: [ { name: 'Imperative vs Declarative programming', id: 'imperative-declarative', description: 'A guide to understanding the difference between Imperative and Declarative programming.', url: 'https://tylermcginnis.com/imperative-vs-declarative-programming/' }, { name: 'Building User Interfaces with Pure Functions and Function Composition', id: 'fn-composition', description: 'A guide to building UI with pure functions and function composition in React', url: 'https://tylermcginnis.com/building-user-interfaces-with-pure-functions-and-function-composition-in-react-js/' } ] } ]
Эта схема будет хорошо отображаться с вложенными маршрутами, и наше приложение в конечном итоге будет выглядеть так
Я призываю вас поиграть с полным примером Здесь Анкет
Прежде чем мы начнем беспокоиться о вложенных маршрутах, давайте сначала создадим скелет нашего приложения, включая Navbar, который позволит нам перемещаться между домом ( /
) и темы ( /темы
).
import React, { Component } from 'react' import { BrowserRouter as Router, Link, Route // for later } from 'react-router-dom' class App extends Component { render() { return () } } export default App
- Home
- Topics
Это солидный старт. Теперь мы хотим сделать несколько <Маршрут>
S так, чтобы пользовательский интерфейс изменился в зависимости от текущего пути, который мы находим. Однако, прежде чем мы сможем это сделать, нам нужно пойти дальше и создать компоненты, которые мы перейдем к нашим <Маршрут>
S рендеринг, если есть матч. – Мы назовем их Главная
и Темы
Анкет На данный момент, пока мы настраиваем вещи, давайте просто сделаем их оба, показывая заголовок, который говорит либо Главная
или Темы
Анкет
function Home () { return (HOME
) } function Topics () { return (TOPICS
) }
Идеальный. Теперь мы будем использовать <Маршрут>
Компонент, чтобы сказать React Router что всякий раз, когда кто -то входит /
, это должно представить Главная
компонент и всякий раз, когда кто -то находит /темы
, это должно представить Темы
составная часть.
class App extends Component { render() { return () } }
- Home
- Topics
На этом этапе у нас есть очень простой пример того, о чем мы говорили ранее, ” и
составная часть . Когда текущее местоположение вашего приложения соответствует
дорожка ,
компонент будет отображаться. Когда это не так,
Маршрут будет ждать ноль ".
Если мы в /
, мы увидим Navbar и Главная
составная часть. Если мы в /темы
, мы увидим Navbar и Темы
составная часть.
Наконец, у нас достаточно хорошего фонтана, чтобы начать говорить о том, как мы занимаемся вложенными маршрутами с React Router. Спасибо за терпение 🤝.
Если вы оглянетесь на Окончательный пример , вы заметите, что когда мы пойдем в /темы
, пользовательский интерфейс, который мы получаем, – это еще один навигал. Давайте изменить наш Темы
компонент, чтобы сделать именно это. На этот раз вместо жесткой кодирования нашего Ссылка на сайт
S, нам нужно использовать наш темы
массив для создания Ссылка
Для каждой темы высокого уровня.
function Topics () { return () }Topics
{topics.map(({ name, id }) => (
- {name}
))}
Теперь, когда мы идем в /темы
и Темы
Компонент отображается, мы получим три Ссылка
S каждый представляет тему высокого уровня. Обратите внимание, где мы ссылаемся, /темы/$ {id}
Анкет Если мы собираемся связать кого -нибудь с /темы/$ {id}
, это означает, что нам нужно отобразить Маршрут
который будет соответствовать этому пути. Это первая большая концепция вложенных маршрутов с React Router – не имеет значения, если вы видите Маршрут
в вашем основном компоненте или в вложенных компонентах, если Путь
Матчи, компонент
будет отображаться. Имея это в виду, что, если мы отобразим Маршрут
Внутри нашего Темы
Компонент и подходит для /темы/: TopeId
?
function Topic () { return (TOPIC) } function Topics () { return () }Topics
{topics.map(({ name, id }) => (
- {name}
))}
🤯🤯🤯🤯🤯🤯
Вот почему понимание Маршрут
было так важно. Сейчас ничего не изменилось с ранее, но по какой -то причине ваш мозг становится все обработанным, так как мы рендеринг Маршрут
За пределами нашего основного Приложение
составная часть.
Что происходит, когда мы идем в /темы
, Тема
компонент отображается. Темы
Затем отдает Navbar и новый Маршрут
который будет соответствовать любому из Ссылка на сайт
S В NAVBAR мы только что отобраны (так как ссылка /темы/: Topicid
) Это означает, что если мы нажмем на любой из Ссылка на сайт
S в Темы
компонент, Тема
Компонент будет отображаться, что сейчас просто говорит, что слово Тема
Анкет
Важно отметить, что только потому, что мы соответствовали другому Маршрут
компонент, это не значит предыдущий Маршрут
S, которые соответствуют, еще не отображаются. Это то, что сбивает с толку многих людей. Помните, подумайте о Маршрут
как рендеринг другого компонента или нулевого. Точно так же, как вы думаете о гнездовании нормальных компонентов в React, может применяться непосредственно к гнездованию Маршрут
с
На данный момент мы хорошо продвигаемся. Что, если по какой -то причине другой член вашей команды, который не знаком с React Router, решил изменить /темы
к /концепции
? Они, вероятно, направились к основному Приложение
компонент и измените Маршрут
//
NBD. Проблема в том, что это полностью разрушает приложение. Внутри Темы
Компонент мы предполагаем, что путь начинается с /темы
Но теперь это было изменено на /концепции
. Нам нужен способ для Темы
компонент, чтобы получить любой начальный путь в качестве опоры. Таким образом, независимо от того, изменит ли кто -то родитель Маршрут
, это всегда будет просто работать. Хорошая новость для нас – React Router делает именно это. Каждый раз, когда компонент отображается с помощью REACT Router, этот компонент проходит три реквизита – расположение
, соответствие
и история
. Тот, о котором нас волнует, соответствие
. соответствие
собирается содержать информацию о том, как Маршрут
были матчи (именно то, что нам нужно). В частности, у него есть два свойства, которые нам нужны, дорожка
и URL
. Они очень похожи, вот как их описывают документы –
Путь – шаблон пути, используемый для соответствия. Полезно для строительства вложенного <Маршрута> s
URL – соответствующая часть URL. Полезно для строительства вложенного s
В этих определениях есть одно важное понимание. Используйте Match.path
Для строительства вложенного Маршрут
s и использовать match.url
Для строительства вложенного Ссылка
с
Лучший способ ответить «почему» – посмотреть на пример.
Если вы не знакомы с параметрами URL, перейдите к React Router V4: параметры URL Прежде чем продолжить.
Предположим, что мы использовали приложение, которое имеет вложенные маршруты, и текущий URL был /темы/React-Router/URL-параметры
Анкет
Если бы мы должны были записать Match.path
и match.url
В самом вложенном компоненте, вот что мы получим.
render() { const { match } = this.props // coming from React Router. console.log(match.path) // /topics/:topicId/:subId console.log(match.url) // /topics/react-router/url-parameters return ... }
Обратите внимание, что Путь
включает параметры URL и URL
это всего лишь полный URL. Вот почему человек используется для Ссылка на сайт
s а также другой используется для Маршрут
с
Когда вы создаете вложенную ссылку, вы не хотите использовать параметры URL. Вы хотите, чтобы пользователь буквально ходил в /темы/React-Router/URL-параметры
Анкет Вот почему match.url
лучше для вложенного Ссылка на сайт
s. Однако, когда вы сопоставляете определенные паттерны с Маршрут
, вы хотите включить параметры URL – вот почему Match.path
используется для вложенного Маршрут
с
Давайте вернемся к нашему примеру, на данный момент мы жестко кодируем /темы
в нашем Маршрут
и Ссылка
с
function Topics () { return () }Topics
{topics.map(({ name, id }) => (
- {name}
))}
Но как мы только что говорили, потому что Темы
отображается с помощью React Router, он дается соответствие
опора мы можем использовать. Мы заменим /темы
часть нашего Ссылка
с match.url
и /темы
часть нашего Маршрут
с Match.path
Анкет
function Topics ({ match }) { return () }Topics
{topics.map(({ name, id }) => (
- {name}
))}
🕺. Хорошая работа.
На этом этапе наше приложение примерно на полпути. Нам все еще нужно добавить еще несколько слоев гнездования. Вот хорошие новости – больше ничего не узнаете в этом уроке. Все, что нам нужно сделать, чтобы завершить оставшиеся вложенные маршруты, о которых мы уже говорили. Мы продолжим создавать новые вложенные Navbars, продолжим рендеринг Маршрут
с И мы продолжим использовать match.url
и матч.path
. Если вам комфортно на данный момент, остальное – соус.
Теперь так же, как и изначально с Темы
Компонент, мы хотим сделать это таким Тема
(No S) также будет отображать вложенную Navbar и Маршрут
. Единственная разница теперь в том, что мы на один уровень глубже, поэтому мы сопоставляем тему Ресурсы
для нашего Ссылка на сайт
s И мы наш Маршрут
будет соответствовать /темы/: Topicid/subid
Анкет
function Resource () { returnRESOURCE
} function Topic ({ match }) { const topic = topics.find(({ id }) => id === match.params.topicId) return () }{topic.name}
{topic.description}
{topic.resources.map((sub) => (
- {sub.name}
))}
Наконец, последнее, что нам нужно сделать, завершить наш Ресурс
составная часть. Поскольку это последний дочерний компонент, мы больше не будем делать больше Ссылка
s или Маршрут
с Вместо этого мы просто дадим ему базовый пользовательский интерфейс, включая имя ресурса, описание и (нормальную) ссылку.
function Resource ({ match }) { const topic = topics.find(({ id }) => id === match.params.topicId) .resources.find(({ id }) => id === match.params.subId) return ( ) }
Вот полный код.
import React, { Component } from 'react' import { BrowserRouter as Router, Route, Link, } from 'react-router-dom' const topics = [ { name: 'React Router', id: 'react-router', description: 'Declarative, component based routing for React', resources: [ { name: 'URL Parameters', id: 'url-parameters', description: "URL parameters are parameters whose values are set dynamically in a page's URL. This allows a route to render the same component while passing that component the dynamic portion of the URL so it can change based off of it.", url: 'https://tylermcginnis.com/react-router-url-parameters' }, { name: 'Programatically navigate', id: 'programmatically-navigate', description: "When building an app with React Router, eventually you'll run into the question of navigating programmatically. The goal of this post is to break down the correct approaches to programmatically navigating with React Router.", url: 'https://tylermcginnis.com/react-router-programmatically-navigate/' } ] }, { name: 'React.js', id: 'reactjs', description: 'A JavaScript library for building user interfaces', resources: [ { name: 'React Lifecycle Events', id: 'react-lifecycle', description: "React Lifecycle events allow you to tie into specific phases of a components lifecycle", url: 'https://tylermcginnis.com/an-introduction-to-life-cycle-events-in-react-js/' }, { name: 'React AHA Moments', id: 'react-aha', description: "A collection of 'Aha' moments while learning React.", url: 'https://tylermcginnis.com/react-aha-moments/' } ] }, { name: 'Functional Programming', id: 'functional-programming', description: 'In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.', resources: [ { name: 'Imperative vs Declarative programming', id: 'imperative-declarative', description: 'A guide to understanding the difference between Imperative and Declarative programming.', url: 'https://tylermcginnis.com/imperative-vs-declarative-programming/' }, { name: 'Building User Interfaces with Pure Functions and Function Composition', id: 'fn-composition', description: 'A guide to building UI with pure functions and function composition in React', url: 'https://tylermcginnis.com/building-user-interfaces-with-pure-functions-and-function-composition-in-react-js/' } ] } ] function Resource ({ match }) { const topic = topics.find(({ id }) => id === match.params.topicId) .resources.find(({ id }) => id === match.params.subId) return ( ) } function Topic ({ match }) { const topic = topics.find(({ id }) => id === match.params.topicId) return () } function Topics ({ match }) { return ({topic.name}
{topic.description}
{topic.resources.map((sub) => (
- {sub.name}
))}
) } function Home () { return (Topics
{topics.map(({ name, id }) => (
- {name}
))}
Home.
) } class App extends Component { render() { return () } } export default App
- Home
- Topics
Поздравляю! Теперь у вас есть возможность создавать вложенные маршруты с помощью React Router. Скажи своей маме, она будет гордиться. 🏅
Оригинал: “https://dev.to/tylermcginnis/nested-routes-with-react-router-v4-3h2j”