Посібник із використання react-router-dom

Будь-який складний застосунок React потребує поділу на декілька сторінок. Для цього необхідно застосувати маршрутизацію в React.

На початку це може здатися складним, але ця інструкція допоможе вам швидко освоїти необхідні основи. У цьому посібнику ми створимо програму, яка використовує маршрутизацію.

Що таке маршрутизація React (маршрутизація на стороні клієнта)?

Маршрутизація в React – це спосіб організації переходів між сторінками в React-застосунку на стороні клієнта. Маршрутизація на стороні клієнта є альтернативою серверній маршрутизації. При серверній маршрутизації браузер надсилає GET-запит до веб-сервера кожного разу, коли користувач переходить на іншу сторінку. Відповідь на цей запит може зайняти певний час.

Для веб-застосунку, де користувач постійно переходить між сторінками, затримка створює незручності. Маршрутизація на стороні клієнта вирішує цю проблему. Замість того, щоб сервер віддавав HTML, програма використовує JavaScript для динамічного створення HTML для різних сторінок.

Для роботи застосунку потрібен лише файл index.html як початкова точка. Потім ця точка входу завантажує JavaScript-код. Цей JavaScript-пакет буде відображати сторінки, маніпулюючи DOM, керуючи маршрутизацією та реалізуючи функціональність застосунку.

Оскільки сервер віддає лише сторінку index.html, застосунок називають односторінковим.

Переваги маршрутизації на стороні клієнта

  • Покращує взаємодію з користувачем, оскільки навігація відбувається швидше, а застосунок стає більш чутливим. При серверній маршрутизації кожен перехід є мережевим запитом із затримкою.
  • Дозволяє створювати автономні застосунки, оскільки весь необхідний код можна кешувати локально. Це робить застосунки більш доступними та пропонує офлайн-функціонал.
  • Застосунок використовує менше даних, оскільки кількість мережевих запитів значно зменшується, якщо все надсилається один раз і деякі файли зберігаються в кеші.
  • Зменшується навантаження на сервер, оскільки сервер повинен відрендерити застосунок лише один раз. Це відрізняється від рендерингу на стороні сервера, де сервер постійно відтворює застосунок.

Далі розглянемо, як впровадити маршрутизацію в React.

Як реалізувати маршрутизацію в React

У цьому посібнику ми створимо просту програму для створення нотаток, яка складатиметься з кількох сторінок. Ми використаємо React Router DOM для маршрутизації на стороні клієнта, щоб користувач міг переміщатися між сторінками. Ми не будемо створювати повний функціонал, зосереджуючись лише на маршрутизації.

Передумови

Для того щоб слідувати цьому посібнику, потрібно мати базові знання HTML, JavaScript та React. Також потрібні Node.js та NPM. Їх можна завантажити та встановити одночасно, встановивши Node.js з офіційного веб-сайту. Або ж скористайтеся інструкціями з вбудованого відео YouTube.

Що ми будемо створювати?

Застосунок матиме декілька сторінок. Завдяки маршрутизації React ви зможете переходити між ними. Нижче наведено макети сторінок.

Домашня сторінка доступна за маршрутом ‘/’.

Сторінка “Про нас” доступна за маршрутом ‘/about’.

Сторінка нотаток доступна за маршрутом ‘/notes’.

Сторінка створення нової нотатки доступна за маршрутом ‘/notes/new’.

Переглянути повну нотатку можна на окремій сторінці. Ця сторінка доступна за маршрутом ‘/routes/‘, де – це ціле число, що є ідентифікатором нотатки, яку потрібно переглянути.

Початок роботи

Для початку створіть новий проект React. Ми будемо використовувати Vite. Команда для ініціалізації нового проєкту така:

npm create vite@latest scribbble --template react

Ми вказали “scribbble” як назву проекту, а React – як шаблон. Далі відкрийте VS Code за допомогою команд:

cd scribbble
code .

Після відкриття VS Code поверніться до терміналу та встановіть react-router-dom. Цей пакет спрощує реалізацію маршрутизації React у ваших програмах.

npm install react-router-dom

Далі створимо файл для зберігання нотаток. Створіть файл src/notes.js і додайте наступний код:

const notes = [
  {
    id: 1,
    title: "Note 1",
    body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
  },
  {
    id: 2,
    title: "Note 2",
    body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
  },
  {
    id: 3,
    title: "Note 3",
    body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
  },
];

export default notes;

Видаліть файл src/App.css, оскільки він не буде потрібен для цього проєкту. Також видаліть імпорт файлу App.css з App.jsx.

Далі, замінити вміст файлу index.css на наступний:

:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;font-weight:400;color:#404040}*{margin:0;padding:0}.nav-container{display:flex;justify-content:space-between;padding:15px 30px}.home-buttons,.nav{display:flex;gap:10px}a{text-decoration:none;color:inherit;font-weight:600}h1{font-size:63px;margin:20px 0}input,textarea{border:1px solid #f1f1f1;background-color:#fafafa;outline:0;padding:10px;width:100%}textarea{resize:none;font-family:inherit}.container{padding:15px}.primary{background-color:#8a2be2;color:#fff}.secondary{background-color:#eee}.button{padding:15px 30px;font-size:16px;border:none;font-weight:700;border-radius:7px;cursor:pointer}.home-container{height:300px;display:flex;flex-direction:column;align-items:center;justify-content:center}.new-note-container{padding:20px}.new-note-form{display:flex;flex-direction:column;align-items:center;width:500px;gap:20px;margin:auto;border-radius:7px;padding:20px 30px}.notes-list{display:grid;grid-template-columns:1fr 1fr 1fr;gap:30px;padding:0 60px}.note{border:1px solid #d3d3d3;padding:15px;border-radius:7px}.note h2{font-size:1rem;margin-bottom:10px}.note p{color:#585858;font-size:.9rem;cursor:pointer}.note-container{display:flex;align-items:center;justify-content:center;padding:50px}.note-content{width:500px}

Далі створіть наступні файли для сторінок:

  • src/pages/Home.jsx
  • src/pages/About.jsx
  • src/pages/Note.jsx
  • src/pages/NewNote.jsx
  • src/pages/Notes.jsx

Створіть також файл для компонента навігаційної панелі за адресою src/components/NavBar.jsx

Налаштування маршрутизації React

Після підготовки програми, налаштуємо маршрутизацію.

Відкрийте файл App.jsx та видаліть його вміст. Потім додайте наступні імпорти у верхній частині файлу:

import { BrowserRouter, Routes, Route } from "react-router-dom";
import { NavBar } from "./components/NavBar";
import { Home } from "./pages/Home";
import { About } from "./pages/About";
import { Notes } from "./pages/Notes";
import { Note } from "./pages/Note";
import { NewNote } from "./pages/NewNote";

Тут ми імпортуємо компоненти BrowserRouter, Routes та Route з react-router-dom. Вони потрібні для налаштування маршрутизатора. Також ми імпортували NavBar з каталогу компонентів та декілька сторінок з файлів сторінок. Ми ще не реалізували ці сторінки, але зробимо це скоро.

Далі налаштуємо компонент застосунку:

export default App () {

}

Додайте таку розмітку в інструкцію return:

return (
    <BrowserRouter>
      
    </BrowserRouter>
)

Тут відтворюється компонент BrowserRouter, наданий react-router-dom. Цей компонент налаштовує маршрутизатор, який працює в браузері. Вміст застосунку буде розташовано всередині цих тегів.

Додамо навігаційну панель та створимо компонент Routes.

return (
    <BrowserRouter>
      <NavBar />
      <div className="container">
        <Routes>
          
        </Routes>
      </div>
    </BrowserRouter>
  );

Всередині елемента BrowserRouter ми додали NavBar. Ми визначимо його пізніше, але він створює посилання у верхній частині кожної сторінки. Замість того щоб писати його для кожної сторінки окремо, ми створимо один NavBar.

Далі створимо елемент контейнера. Він не є обов’язковим для маршрутизації. Ми просто додали його для застосування стилів.

Всередині контейнера ми додали компонент Routes. Тут будуть відображатися різні сторінки залежно від маршруту, на якому знаходиться браузер. Вміст компонента Routes буде перерендеритися щоразу, коли маршрут змінюється.

Нарешті, додамо маршрути для різних сторінок.

  return (
    <BrowserRouter>
      <NavBar />
      <div className="container">
        <Routes>
          <Route path="/" Component={Home} />
          <Route path="about" Component={About} />
          <Route path="notes" Component={Notes}>
            <Route path="new" Component={NewNote} />
            <Route path=":id" Component={Note} />
          </Route>
        </Routes>
      </div>
    </BrowserRouter>
  );

Компонент “Домашня сторінка” буде відображатися при шляху ‘/’, компонент “Про нас” за маршрутом ‘/about’. Компонент Notes відображається за маршрутом ‘/notes’. Також є вкладені маршрути ‘/notes/new’ та ‘/notes/:id’.

Пояснення вкладених маршрутів

Маршрут може містити внутрішні маршрути. Вони називаються вкладеними маршрутами. Шлях до цих вкладених маршрутів буде доданий до батьківського маршруту, утворюючи повний шлях. Наприклад, маршрути ‘notes’ та ‘new’ об’єднаються у ‘/notes/new’.

Щодо відображення компонентів, то при переході до батьківського маршруту відобразиться лише батьківський компонент. При переході до вкладеного маршруту будуть відображені і батьківський, і вкладений компоненти.

Для того, щоб відобразити обидва компоненти разом, компонент Notes має використовувати компонент Outlet, який визначає, де буде вбудовано компонент Note. Ви побачите це пізніше, коли ми почнемо створювати сторінки.

Динамічні маршрути

Раніше ми вказували точні маршрути, з якими потрібно збігатися, наприклад ‘/’, ‘about’. React-router-dom дозволяє вказувати динамічні маршрути. Динамічний маршрут містить частину, яка може бути зіставлена з параметром запиту. При збігу, цей параметр передається на сторінку.

Наприклад, у батьківському маршруті ‘posts’ є вкладений маршрут із динамічною частиною ‘:id’. Цей маршрут приймає будь-який текст на місці ‘:id’, і цей текст стане доступним для компонента Note як id.

Створення панелі навігації

Для навігації через react-router-dom ми використовуємо компоненти Link замість звичайних тегів посилання. Отже, навігаційна панель виглядатиме так:

import { Link } from "react-router-dom";

export function NavBar() {
  return (
    <div className="nav-container">
      <Link to="/">Scribbble</Link>
      <nav className="nav">
        <Link to="/about">About</Link>
        <Link to="/notes">Notes</Link>
        <Link to="/notes/new">New Note</Link>
      </nav>
    </div>
  );
}

Додайте цей код у src/pages/NavBar.jsx.

Створення сторінок

Далі створимо сторінки. Для домашньої сторінки додайте наступний код у src/pages/Home.jsx.

import { useNavigate } from "react-router-dom";

export function Home() {
  const navigate = useNavigate();

  return (
    <div className="home-container">
      <h1>Notes for professionals</h1>
      <div className="home-buttons">
        <button
          onClick={() => {
            navigate("/notes/new");
          }}
          className="button primary"
        >
          Start Scribbling
        </button>
        <button
          onClick={() => {
            navigate("/notes");
          }}
          className="button secondary"
        >
          View Notes
        </button>
      </div>
    </div>
  );
}

На домашній сторінці ми хочемо використовувати кнопки для навігації, тому використовуємо хук useNavigate для програмної навігації. Ми імпортували хук, а потім викликали його в Home Component. Значення, що повертається після виклику хука – це функція, яку можна використовувати для навігації.

Далі визначимо сторінку “Про нас”. Додайте наступний код у файл src/pages/About.jsx.

export function About() {
  return (
    <div>
      <h1>About</h1>
      <p>Simple Notes is the best note-taking application for professionals</p>
    </div>
  );
}

Після цього визначимо сторінку “Нотатки”.

У цей компонент потрібно включити компонент Outlet, який буде використовуватися для відображення вкладених маршрутів. Тому сторінка src/pages/Notes.jsx має такий вигляд:

import { Outlet, useNavigate } from "react-router-dom";
import notes from "../notes";

export function Notes() {
  const navigate = useNavigate();
  return (
    <div>
      <Outlet />
      <div className="notes-list">
        {notes.map((note) => {
          return (
            <div
              className="note"
              key={note.id}
              onClick={() => {
                navigate("/notes/" + note.id);
              }}
            >
              <h2>{note.title}</h2>
              <p>{note.body.slice(0, 100)}</p>
            </div>
          );
        })}
      </div>
    </div>
  );
}

Далі визначимо сторінку Note.

Вона буде відображатися для окремої нотатки. Щоб обрати нотатку для рендерингу, Notes отримає доступ до ідентифікатора, вказаного в динамічній частині маршруту. Для цього використовується хук useParams. Таким чином, код у файлі src/pages/Note.jsx має бути таким:

import { useParams } from "react-router-dom";
import notes from "../notes";

export function Note() {
  const params = useParams();
  const note = notes.find((note) => note.id == params.id);
  return (
    <div className="note-container">
      <div className="note-content">
        <h2>{note.title}</h2>
        <p>{note.body}</p>
      </div>
    </div>
  );
}

Нарешті, створимо компонент NewNote у src/pages/NewNote.jsx з таким кодом:

export function NewNote() {
  return (
    <div class="new-note-container">
      <form class="new-note-form">
        <h2>New Note</h2>
        <input type="text" name="title" placeholder="Note title" />
        <textarea rows="10" placeholder="Note text" />
        <button class="button primary">Save Note</button>
      </form>
    </div>
  );
}

На цьому етапі ми написали весь код застосунку. Запустіть програму за допомогою `npm run dev`. Перейдіть на різні сторінки та перевірте швидкість маршрутизації на стороні клієнта.

Недоліки маршрутизації на стороні клієнта

Незважаючи на численні переваги, маршрутизація на стороні клієнта має декілька недоліків. Ось деякі з них:

  • Перше завантаження сторінки може бути повільним, оскільки потрібно завантажити всю програму. JavaScript-пакет може бути дуже великим і завантажуватися довго.
  • Оскільки JavaScript генерує розмітку, сторінка може бути неоптимізованою для SEO.
  • Оскільки все залежить від JavaScript, браузери, які не підтримують JavaScript або в яких він вимкнений, не зможуть запустити програму.

Висновок

У цій статті ми розглянули маршрутизацію React, створивши невеличкий проєкт. Хоча ми не охопили все, цей посібник містить концепції, які ви будете використовувати в більшості проєктів. Для отримання додаткової інформації про react-router-dom перегляньте офіційну документацію.

Далі прочитайте цю статтю про бібліотеки форм React.