Українська

Досліджуйте основні патерни навігації з React Router v6. Вивчіть декларативну маршрутизацію, динамічні маршрути, програмну навігацію, вкладені маршрути та стратегії завантаження даних для створення надійних і зручних вебзастосунків.

React Router v6: Опанування патернів навігації для сучасних вебзастосунків

React Router v6 — це потужна та гнучка бібліотека маршрутизації для React-застосунків. Вона дозволяє створювати односторінкові застосунки (SPA) з безшовним користувацьким досвідом, керуючи навігацією без повних перезавантажень сторінки. Цей допис у блозі заглибиться в основні патерни навігації з використанням React Router v6, надаючи вам знання та приклади для створення надійних і зручних вебзастосунків.

Розуміння основних концепцій React Router v6

Перш ніж заглиблюватися в конкретні патерни, розглянемо деякі фундаментальні концепції:

1. Декларативна маршрутизація з <Routes> та <Route>

Основою React Router v6 є декларативна маршрутизація. Ви визначаєте свої маршрути за допомогою компонентів <Routes> та <Route>. Компонент <Routes> діє як контейнер для ваших маршрутів, а компонент <Route> визначає конкретний маршрут і компонент для рендерингу, коли цей маршрут відповідає поточній URL-адресі.

Приклад: Базова конфігурація маршрутів

Ось базовий приклад налаштування маршрутів для простого застосунку:


import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";

function App() {
  return (
    
      
        } />
        } />
        } />
      
    
  );
}

export default App;

У цьому прикладі ми визначаємо три маршрути:

Компонент BrowserRouter вмикає маршрутизацію на основі історії браузера. React Router зіставляє поточну URL-адресу з визначеними маршрутами та рендерить відповідний компонент.

2. Динамічні маршрути з параметрами URL

Динамічні маршрути дозволяють створювати маршрути, які можуть обробляти різні значення в URL. Це корисно для відображення контенту на основі унікального ідентифікатора, такого як ID продукту або ID користувача. React Router v6 використовує символ : для визначення параметрів URL.

Приклад: Відображення деталей продукту

Припустимо, у вас є застосунок для електронної комерції, і ви хочете відображати деталі для кожного продукту на основі його ID. Ви можете визначити динамічний маршрут таким чином:


import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";

function ProductDetails() {
  const { productId } = useParams();

  // Fetch product details based on productId
  // ...

  return (
    

Product Details

Product ID: {productId}

{/* Display product details here */}
); } function App() { return ( } /> ); } export default App;

У цьому прикладі:

Приклад інтернаціоналізації: Обробка мовних кодів

Для багатомовного вебсайту ви можете використовувати динамічний маршрут для обробки мовних кодів:


} />

Цей маршрут буде відповідати URL-адресам, таким як /en/about, /fr/about та /es/about. Параметр lang потім можна використовувати для завантаження відповідних мовних ресурсів.

3. Програмна навігація з useNavigate

Хоча декларативна маршрутизація чудово підходить для статичних посилань, часто потрібно здійснювати навігацію програмно на основі дій користувача або логіки застосунку. Для цього React Router v6 надає хук useNavigate. useNavigate повертає функцію, яка дозволяє вам переходити до різних маршрутів.

Приклад: Перенаправлення після відправки форми

Припустимо, у вас є відправка форми, і ви хочете перенаправити користувача на сторінку успіху після успішної відправки форми:


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

function MyForm() {
  const navigate = useNavigate();

  const handleSubmit = async (event) => {
    event.preventDefault();

    // Submit the form data
    // ...

    // Redirect to the success page after successful submission
    navigate("/success");
  };

  return (
    
{/* Form fields */}
); } export default MyForm;

У цьому прикладі:

Передача стану під час навігації

Ви також можете передавати стан разом з навігацією, використовуючи другий аргумент для navigate:


navigate("/confirmation", { state: { orderId: "12345" } });

Це дозволяє передавати дані до цільового компонента, доступ до яких можна отримати за допомогою хука useLocation.

4. Вкладені маршрути та макети

Вкладені маршрути дозволяють створювати ієрархічні структури маршрутизації, де один маршрут вкладений в інший. Це корисно для організації складних застосунків з кількома рівнями навігації. Це допомагає створювати макети, де певні елементи інтерфейсу послідовно присутні в усій секції застосунку.

Приклад: Секція профілю користувача

Припустимо, у вас є секція профілю користувача з вкладеними маршрутами для відображення інформації профілю користувача, налаштувань та замовлень:


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Profile() {
  return (
    

User Profile

  • Profile Information
  • Settings
  • Orders
} /> } /> } />
); } function ProfileInformation() { return

Profile Information Component

; } function Settings() { return

Settings Component

; } function Orders() { return

Orders Component

; } function App() { return ( } /> ); } export default App;

У цьому прикладі:

Символ * у батьківському маршруті є вирішальним; він означає, що батьківський маршрут повинен відповідати будь-якому підшляху, дозволяючи вкладеним маршрутам правильно зіставлятися всередині компонента Profile.

5. Обробка помилок "Не знайдено" (404)

Важливо обробляти випадки, коли користувач переходить на маршрут, якого не існує. React Router v6 робить це легко за допомогою універсального маршруту (catch-all route).

Приклад: Реалізація сторінки 404


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function NotFound() {
  return (
    

404 - Not Found

The page you are looking for does not exist.

Go back to home
); } function App() { return ( } /> } /> } /> ); }

У цьому прикладі:

6. Стратегії завантаження даних з React Router v6

React Router v6 не включає вбудованих механізмів завантаження даних, як його попередник (React Router v5 з `useRouteMatch`). Однак він надає інструменти для ефективної реалізації різних стратегій завантаження даних.

Варіант 1: Запит даних у компонентах

Найпростіший підхід — це запитувати дані безпосередньо в компоненті, який рендерить маршрут. Ви можете використовувати хук useEffect для запиту даних, коли компонент монтується або коли змінюються параметри URL.


import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";

function ProductDetails() {
  const { productId } = useParams();
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchProduct() {
      try {
        const response = await fetch(`/api/products/${productId}`);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        setProduct(data);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchProduct();
  }, [productId]);

  if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; if (!product) return

Product not found

; return (

{product.name}

{product.description}

); } export default ProductDetails;

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

Варіант 2: Використання власного хука для завантаження даних

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


import { useState, useEffect } from "react";

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

Потім ви можете використовувати цей хук у своїх компонентах:


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

function ProductDetails() {
  const { productId } = useParams();
  const { data: product, loading, error } = useFetch(`/api/products/${productId}`);

  if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; if (!product) return

Product not found

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Варіант 3: Використання бібліотеки маршрутизації з можливостями завантаження даних (TanStack Router, Remix)

Бібліотеки, такі як TanStack Router та Remix, пропонують вбудовані механізми завантаження даних, які безшовно інтегруються з маршрутизацією. Ці бібліотеки часто надають такі функції:

Використання такої бібліотеки може значно спростити завантаження даних та покращити продуктивність, особливо для складних застосунків.

Рендеринг на стороні сервера (SSR) та генерація статичних сайтів (SSG)

Для покращення SEO та продуктивності початкового завантаження, розгляньте можливість використання SSR або SSG з фреймворками, такими як Next.js або Gatsby. Ці фреймворки дозволяють завантажувати дані на сервері або під час збірки та подавати попередньо відрендерений HTML клієнту. Це усуває необхідність клієнта завантажувати дані при початковому завантаженні, що призводить до швидшого та більш SEO-дружнього досвіду.

7. Робота з різними типами роутерів

React Router v6 надає різні реалізації роутерів для різних середовищ та випадків використання:

Обирайте тип роутера, який найкраще відповідає вимогам та середовищу вашого застосунку.

Висновок

React Router v6 надає комплексне та гнучке рішення для маршрутизації в React-застосунках. Розуміючи та застосовуючи патерни навігації, обговорені в цьому дописі, ви можете створювати надійні, зручні та легкі для підтримки вебзастосунки. Від декларативної маршрутизації з <Routes> та <Route> до динамічних маршрутів з параметрами URL, програмної навігації з useNavigate та ефективних стратегій завантаження даних, React Router v6 дає вам змогу створювати безшовний навігаційний досвід для ваших користувачів. Розгляньте можливість вивчення просунутих бібліотек маршрутизації та фреймворків SSR/SSG для ще більшого контролю та оптимізації продуктивності. Пам'ятайте про адаптацію цих патернів до конкретних вимог вашого застосунку та завжди надавайте пріоритет зрозумілому та інтуїтивному користувацькому досвіду.