React - это библиотека JavaScript для создания пользовательских интерфейсов. В парадигме React каждая часть пользовательского интерфейса является компонентом, который управляет своим собственным автономным состоянием (данными) и функциями.

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

Хотя SPA обеспечивают пользователям удобную навигацию, ожидаются функции маршрутизации традиционных веб-сайтов.

Например:

  • у каждого представления на экране должен быть свой собственный URL-адрес, чтобы я мог добавить страницу в закладки.
  • Кнопки вперед и назад должны перемещать меня вперед или назад в моей истории просмотров.
  • Вложенные представления и представления с параметрами должны поддерживаться, например example.com/products/shoes/101.

В сообществе React React Router - любимая библиотека для обработки маршрутизации. Самым привлекательным аспектом этой версии библиотеки является то, что она «просто React». Маршруты - это просто компоненты, которые отображаются на экране при запуске приложения. Они не определены во внешних файлах, как в других фреймворках.

Предпосылки

Вам потребуется следующее: Базовые знания React, Git установлен на вашем компьютере и NPM установлен. на вашем компьютере r.

Настройка

Если у вас установлен Git, найдите пустые исходные файлы (в ветке master) и клонируйте их на свой компьютер, используя:

git clone https://github.com/emmyyusufu/react-router-demos.git

Откройте папку в текстовом редакторе и найдите вложенные папки внутри:

Это сообщение разделено на четыре подраздела в соответствии с папками: Basic routing, Nested routing, Nested routing with path parameters и Authenticated routing.

Чтобы запустить демонстрационные версии, откройте заданную папку в вашем терминале, затем запустите npm install, а затем npm start.

# 1 Базовая маршрутизация

Начнем с нуля. Обратите внимание на структуру папок основной папки маршрутизации.

Все демонстрации в этом посте изначально были созданы с использованием create-react-app. Это дает некоторые преимущества, такие как уже настроенный сервер Webpack, который объединит весь файл JavaScript в нашем приложении в файл bundle.js , который будет прикреплен к index.html file во время выполнения. Во время выполнения сервер разработки Webpack будет отслеживать любые изменения в нашем файле и обновлять его по мере выполнения приложения во время разработки.

Я создал components/ папку, в которой хранятся все наши компоненты. Обратите внимание, что:

  • index.js это входной файл для всех .js файлов в нашем приложении. Здесь будет выполняться объединение Webpack, поэтому все .js файлы должны быть импортированы в него.
  • App.js будет содержать все, что касается нашего приложения React.

По умолчанию приложение create-response-app не помещает App.js в эту папку. Но поскольку я изменил структуру папок, я внес соответствующие изменения в URL-адрес пути и импортировал его в index.js. Чтобы узнать больше о приложении create-react-app, эта справка будет полезна.

Перейдите в первую папку 01-basic-routing и запустите npm install.

Откройте файл App.js, и вы должны увидеть следующее:

import React, { Component } from 'react';
import '../styles/App.css';
// import route Components here
class App extends Component {
  render() {
    return (
      <div className="App">
<div className="container">
          <ul>
            <li><a href="">Hello</a></li>
            <li><a href="">About</a></li>
            <li><a href="">Books</a></li>
          </ul>
          <hr/>
{/* Routes will go here */}
</div>
</div>
    );
  }
}
export default App;

Запустите npm start и просмотрите приложение. Изменений пока нет.

Давайте установим React Router через NPM. Открыв папку в вашем терминале, запустите:

npm install react-router-dom

Почему react-router-dom? Это связано с тем, что библиотека маршрутизатора React состоит из трех пакетов: react-router, react-router-dom и react-router-native.

react-router - это основной пакет для маршрутизатора, тогда как два других зависят от среды. Вам следует использовать react-router-dom , если вы создаете для Интернета, и react-router-native, если вы работаете в среде разработки мобильных приложений с помощью React Native.

Импортируйте следующее в App.js

// import route Components here
import {
  BrowserRouter as Router,
  Route,
  Link,
  Switch,
  Redirect
} from 'react-router-dom'

Позже мы поймем, что делают эти компоненты. Все компоненты маршрутизации зависят от BrowserRouter предоставления им API истории браузера HTML5.

Обратите внимание, что в компонентах React первая буква написана с заглавной буквы, чтобы их можно было идентифицировать иначе, чем теги HTML по умолчанию.

History API - это объект, который позволяет нам управлять текущим местоположением через history.location, а также предыдущими местоположениями. Думайте о свойстве location объекта как о массиве. Текущее местоположение - это последний элемент в массиве, и мы манипулируем массивом с помощью таких методов, как history.push() илиhistory.replace. Какие бы манипуляции с массивом ни производились, это вызовет переход страницы в текущее местоположение. Вот что происходит за кулисами при использовании компонентов Link и Redirect, как мы скоро увидим.

Мы импортировали содержимое BrowserRouter в переменную Router. Нам нужно обернуть им все наше приложение, чтобы оно предоставляло необходимые API по всему приложению. В App.js добавить:

import React, { Component } from 'react';
import '../styles/App.css';
// import route Components here
import {
  BrowserRouter as Router,
  Route,
  Link,
  Switch,
  Redirect
} from 'react-router-dom'
class App extends Component {
  render() {
    return (
      <Router>
        <div className="App">
<div className="container">
            <ul>
              <li><a href="">Hello</a></li>
              <li><a href="">About</a></li>
              <li><a href="">Books</a></li>
            </ul>
            <hr/>
{/* Routes will go here */}
</div>
        </div>
      </Router>
    );
  }
}
export default App;

Компонент ‹Маршрут /›

Приступим к изучению компонента Route. Этот компонент отображает страницу, если текущее расположение URL совпадает с указанным в нем параметром path. Он также принимает реквизиты component, render и children.

Давайте создадим наш, где его написанные {/ * Routes будут идти сюда * /}:

<Route path="/hello" component={Hello} />
<Route path="/about" component={About} />
<Route path="/books" component={Books} />

Но этих компонентов не существует! Да ты прав.

Опять же, прежде чем мы их создадим, давайте добавим еще импорт в App.js. Импорт из HelloComponent.js, AboutComponent.js и BooksComponent.js с использованием Hello, About и Books в качестве переменных. В опоре component={} фигурные скобки используются для обозначения переменных, а не строк.

import React, { Component } from 'react';
import '../styles/App.css';
import Hello from './HelloComponent';
import About from './AboutComponent';
import Books from './BooksComponent';
// import route Components here
import {
  BrowserRouter as Router,
  Route,
  Link,
  Switch,
  Redirect
} from 'react-router-dom'

Обратите внимание, что render похож на component={}, но позволяет нам определять компонент прямо здесь:

<Route path="/hello" render={() => {
           return (
              <div className="jumbotron">
                <h1 className="display-3">Hello, world!</h1>
              </div>
             );
      }}/>

Перейдите к пустому файлу HelloComponent.js и вставьте:

import React from 'react';
const Hello = () => {
    return (
        <div className="jumbotron">
            <h1 className="display-3">Hello, world!</h1>
        </div>
    );
}
export default Hello;

Выше мы использовали функциональный компонент без сохранения состояния (отсюда и стрелочную функцию). Мы используем их для компонентов, которые отображают на веб-страницу только статический контент, в отличие от компонентов, которые отображают / изменяют контент с сохранением состояния.

Если вы не заметили, мы используем стили Bootstrap 4 в нашем App.css файле, отсюда класс jumbotron в div.

// inside App.css. You'll need internet connection to load the Bootstrap 4 styles.
.App {
  padding-top: 50px;
}
@import url('https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css');

Перейдите к пустому файлу AboutComponent.js и вставьте:

import React from 'react';
const About = () => {
    return (
        <div className="jumbotron">
            <h1 className="display-3">About Me</h1>
        </div>
    );
}
export default About;

Наконец, перейдите к пустому файлу BooksComponent.js и вставьте:

import React from 'react';
const Books = () => {
    return (
        <div className="jumbotron">
            <h1 className="display-3">My Books</h1>
        </div>
    );
}
export default Books;

Еще одна вещь, которую нам нужно завершить в этом разделе, - это компонент Link.

Компонент ‹Link› ‹/Link›

Он заменяет HTML-тег <a href=""></a> по умолчанию. Он принимает опору to="", которая указывает на адрес URL, по которому мы хотим перейти.

Внутри App.js замените теги привязки по умолчанию на Link:

<ul>
   <li><Link to="/hello">Hello</Link></li>
   <li><Link to="/about">About</Link></li>
   <li><Link to="/books">Books</Link></li>
</ul>

Запустите npm start со своего терминала и посмотрите полное приложение:

Как вы визуализируете компонент, если посещается / URL, например, целевая или домашняя страница. Возможно, вы захотите создать для него маршрут:

<Route path="/" component={Home} />

Это нормально, но помните, что в других путях есть /. Поэтому, если мы посетили другие URL-адреса, такие как /hello, /about и /books, компонентHome будет продолжать отображаться по умолчанию. Чтобы исправить это, напишите другую опору exact, установив для нее значение true, или просто напишите exact.

<Route path="/" exact={true} component={Home} />

Это гарантирует, что компонент Home будет отображаться только в тех случаях, когда URL-адрес в точности совпадает с этим: /.

Создайте новый HomeComponent.js файл в папке components/ . Вставьте это в:

import React from 'react';
const Home = () => {
    return (
        <div className="jumbotron">
            <h1 className="display-3">Landing page</h1>
        </div>
    );
}
export default Home;

Импортировать в App.js

import Home from './HomeComponent';

Добавить в список маршрутов

<Route exact={true} path="/" component={Home} />
<Route path="/hello" component={Hello} />
<Route path="/about" component={About} />
<Route path="/books" component={Books} />

Посетите http://localhost:3000 и просмотрите:

Проведите несколько экспериментов. Удалите exact={true} из домашнего маршрута и посмотрите, что произойдет. Вы поймете, почему это важно.

Компонент ‹Switch› ‹/Switch›

При необходимости для реализации потребуется обернуть его вокруг компонентов Route. При посещении пути URL-адреса допускается отображение только первого <Route>, соответствующего пути.

Ранее у нас была проблема с / рендерингом Home компонента и других путей. Если мы создадим путь /hello/goodmorning, что будет? Будут визуализированы компоненты пути /hello и /hello/goodmorning. Switch снова поможет в этом случае, выбрав только один маршрут для рендеринга, но самый важный маршрут должен быть организован так, чтобы он шел первым.

Используя Switch, мы можем избежать того, что происходит на изображении выше, но только для URL, отличных от /. exact={true} обрабатывает это за /. Помните, что Switch выберет только первое совпадение Route. Давайте поработаем и посмотрим на результат.

<Switch>
    <Route exact path="/" component={Home} />
    <Route path="/hello" component={Hello} />
    <Route path="/hello/goodmorning" render={() => { return      <h1>Goodmorning</h1> }} />
    <Route path="/books" component={Books} />
</Switch>

Кроме того, Switch позволяет нам указать маршрут для отображения, если URL-адрес не соответствует местоположению. Для этого маршрута оставьте опору path пустой.

// Just an example. Don't implement. This catch-all Route would be at the bottom if implemented.
<Route component={NoMatch} />

Таким образом, Switch сделает следующее:

  • Избегайте инклюзивного рендеринга маршрута.
  • включите всеобъемлющий маршрут в нижней части нашего контейнера Switch.

# 2 Вложенная маршрутизация

Помните, что мы могли визуализировать компоненты через Route inline или указав компонент:

<Route component={SomeComponent}/>

Or

<Route render={() => { return <h1>Soemthing</h1> }/>

Компоненту, который будет создан с помощью Route, автоматически будут переданы следующиеprop объекты:

  • соответствие
  • место нахождения
  • история

Мы рассмотрим только использование match, поскольку он полезен для реализации вложенных маршрутов. Объект match содержит следующие свойства:

  • params - (объект) пары ключ / значение, извлеченные из URL-адреса, соответствующего динамическим сегментам пути.
  • isExact - (логическое) true, если был найден весь URL (без завершающих символов).
  • путь - (строка) шаблон пути, используемый для сопоставления. Полезно для построения вложенных ‹Route› s
  • url - (строка) совпавшая часть URL-адреса. Полезно для построения вложенных ‹Link› s

Мы хотим добавить новые маршруты в маршрут /book. Это будут книги:

  • HTML
  • CSS
  • Реагировать

Перейдите во вторую подпапку 02-nested-routing на вашем терминале и запустите npm install.

В редакторе кода откройте BookComponent.js и измените:

const Books = ({ match }) => {
    return (
<div>
   <div className="jumbotron">
        <h1 className="display-3">My Books</h1>
   </div>
  <div className="container">
    <div className="row">
      <div className="col-md-3">
          <ul>
            <li><Link to="">HTML</Link></li>
            <li><Link to="">CSS</Link></li>
            <li><Link to="">React</Link></li>
          </ul>
      </div>
      <div className="col-md-9">
               {/* place routes here */}
      </div>
    </div>
   </div>
</div>
    );
}

Давайте установим React Router через NPM. Открыв папку в вашем терминале, запустите:

npm install react-router-dom

Синтаксически мы продемонстрировали, что объект match передается как props. Помните, что используемые классы предназначены для того, чтобы стили Bootstrap вступили в силу. Не забудьте импортировать все компоненты React Router после импорта React:

import React from 'react';
import {
    BrowserRouter as Router,
    Route,
    Link,
    Switch,
    Redirect
  } from 'react-router-dom';

Нам не нужно было импортировать их все, но мы все равно это сделали. Разместите маршруты:

<Route path="" render={() => { return <h1>HTML by Ducket book</h1> }}/>
<Route path="" render={() => { return <h1>CSS by Racheal Andrews</h1> }}/>
<Route path="" render={() => { return <h1>React by Fullstack.io book</h1> }}/>

Мы используем рендеринг встроенных компонентов, чтобы сэкономить время. Теперь давайте заполним to="" из Link и path="" из Route.

Сделайте эти изменения:

<div className="col-md-3">
    <ul>
      <li><Link to={`${match.url}/html`}>HTML</Link></li>
      <li><Link to={`${match.url}/css`}>CSS</Link></li>
      <li><Link to={`${match.url}/react`}>React</Link></li>
     </ul>
</div>
 <div className="col-md-9">
      <Route path={`${match.path}/html`} render={() => { return <h1>HTML by Ducket book</h1> }}/>
      <Route path={`${match.path}/css`} render={() => { return <h1>CSS by Racheal Andrews</h1> }}/>
      <Route path={`${match.path}/react`} render={() => { return <h1>React by Fullstack.io book</h1> }}/>
</div>

${match.url} оценивается как /books, а ${match.path} оценивается как localhost://3000/books.. Используемые обратные тики - это способ объединения строк, содержащих переменные, в ES6.

Сохраните его, запустите npm start и просмотрите работающее приложение.

# 3 Вложенная маршрутизация с параметрами пути

Любой URL-адрес, заканчивающийся на _120 _, _ 121_ или /:whatever, указывает, что эта часть является динамически сгенерированной частью URL-адреса, которая может иметь любое значение.

Мы можем получить доступ к таким частям через match.params.id для использования в маршрутизации.

Снова откройте третью подпапку 03-nested-routing-with-path-parameters в вашем терминале и запустите npm install.

Кроме того, давайте установим React Router через NPM. Открыв папку в вашем терминале, запустите:

npm install react-router-dom

Чтобы проиллюстрировать, как параметры пути могут использоваться для маршрутизации, вставьте следующее в Book.js:

import React from 'react';
import {
    BrowserRouter as Router,
    Route,
    Link,
    Switch,
    Redirect
  } from 'react-router-dom';
const Books = ({ match }) => {
    return (
        <div>
            <div className="jumbotron">
                <h1 className="display-3">My Books</h1>
            </div>
<div className="container">
          <div className="row">
              <div className="col-md-3">
          <ul>
              <li><Link to={`${match.url}/html`}>HTML</Link></li>
              <li><Link to={`${match.url}/css`}>CSS</Link></li>
              <li><Link to={`${match.url}/react`}>React</Link></li>
          </ul>
                </div>
                <div className="col-md-9">
                    <Route path={`${match.path}/html`} render={() => { return <h1>HTML by Ducket book</h1> }}/>
                    <Route path={`${match.path}/css`} render={() => { return <h1>CSS by Racheal Andrews</h1> }}/>
                    <Route path={`${match.path}/react`} render={() => { return <h1>React by Fullstack.io book</h1> }}/>
                    <Route path={`${match.path}/:id`} component={Child} />
                </div>
            </div>
            </div>
        </div>
    );
}
const Child = ({ match }) => (
    <div>
      <h3>URL ID parameter: {match.params.id}</h3>
    </div>
);
export default Books;

Запустите npm start.

# 4 Маршрутизация защищенного пути

Этот вид маршрутизации предназначен для страниц веб-сайта, которым требуется, чтобы пользователь вошел в систему и прошел аутентификацию перед просмотром таких страниц. Примером может служить страница администратора .

Для обработки защищенных путей нам понадобится <Redirect/> (стандартный компонент) и <PrivateRoute/> (пользовательский компонент).

<PrivateRoute/> не является стандартным <Route/> компонентом. Стандартный компонент маршрута, предоставляемый React Router, - это<Route/>. Мы определим <PrivateRoute/> как наш собственный <Route/>.

Пользовательские маршруты необходимы, когда нам нужно принять решение, нужно ли отображать <Route/> интересующий нас объект. Как вы увидите в коде, мы перечислим <PrivateRoute/> вместе с другими <Route/>.

Компонент ‹Redirect /›

Визуализация ‹Redirect› приведет к переходу в новое место. Новое местоположение переопределит текущее местоположение в стеке истории, как это делают перенаправления на стороне сервера (HTTP 3xx).

<Redirect/> имеет несколько свойств, но мы будем использовать свойство объекта to следующим образом:

<Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>

При использовании это перенаправляет на путь /login. Информация о последнем местоположении перед выполнением перенаправления будет доступна компоненту LoginPage через this.props.location.state.

Перейдите к последней подпапке 04-authenticated-routing. Запустите npm install.

Установите React Router через NPM. Открыв папку в вашем терминале, запустите:

npm install react-router-dom

Откройте App.js и добавьте новый элемент списка /admin к существующим.

<ul>
     <li><Link to="/hello">Hello</Link></li>
     <li><Link to="/about">About</Link></li>
     <li>
         <Link to="/books">Books</Link>
     </li>
     <li>
         <Link to="/admin">Admin</Link>
     </li>
</ul>

Добавьте маршруты <PrivateRoute/> и /login к группе существующих <Route/>s.

<Switch>
            <Route exact path="/" component={Home} />
            <Route path="/about" component={About} />
            <Route path="/hello" component={Hello} />
            <Route path="/books" component={Books} />
            <Route path="/login" component={Login}/>
            <PrivateRoute authed={fakeAuth.isAuthenticated} path="/admin" component={Admin} />
          </Switch>

Теперь создайте компонент <PrivateRoute/> вне компонента App:

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)

<PrivateRoute/> в конечном итоге отобразит компонент <Route>. Компонент <Route> использует троичную операцию для определения того, что отображать, в зависимости от того, вошел ли пользователь в систему или нет: <Redirect/> на страницу входа или Admin компонент страницы.

Создайте компонент Admin:

const Admin = () => {
  return (
    <div className="jumbotron">
      <h3 className="display-3">Admin Access granted</h3>
    </div>
  );
}

Также создайте компонент Login:

class Login extends React.Component {
  
    constructor() {
      super();
  
      this.state = {
        redirectToReferrer: false
      }
      // binding 'this'
      this.login = this.login.bind(this);
    }
  
    login() {
  
      fakeAuth.authenticate(() => {
        this.setState({ redirectToReferrer: true })
      })
    }
  
    render() {
      const { from } = this.props.location.state || { from: { pathname: '/' } }
      const { redirectToReferrer } = this.state;
  
      if (redirectToReferrer) {
        return (
          <Redirect to={from} />
        )
      }
  
      return (
        <div className="jumbotron">
            <h1 className="display-3">Login required</h1>
            <p className="lead">You must log in to view the page at {from.pathname}.</p>
            <p className="lead">
              <a className="btn btn-primary btn-lg" onClick={this.login} role="button">Login</a>
            </p>
        </div>
      )
    }
  }
  
  /* A fake authentication function */
  export const fakeAuth = {
  
    isAuthenticated: false,
    authenticate(cb) {
      this.isAuthenticated = true
       setTimeout(cb, 100)
    },
  }

Этот Login компонент реализует функцию фальшивой аутентификации, которая устанавливает для пользователя вход в систему или выход из нее.

Запускаем npm start и видим работающее приложение.

На этом мы подошли к концу статьи. Слава вам, если вы зашли так далеко. Если вы хотите получить более подробную информацию о React Router, просмотрите Документацию.

Если вам нужна завершенная версия кода, посетите завершенную ветку на Github.

Не стесняйтесь поддерживать меня (devapparel.co) и хорошо выглядеть при этом. Также прокомментируйте или поделитесь этим сообщением. Спасибо за прочтение!

Изначально опубликовано в Zeolearn Blog.