JavaRush /Курсы /Модуль 3: React /Работа с getStaticPaths для динамических маршрутов

Работа с getStaticPaths для динамических маршрутов

Модуль 3: React
14 уровень , 4 лекция
Открыта

Что такое getStaticPaths?

getStaticPaths — это асинхронная функция, предоставляемая Next.js, которая используется для генерации динамических маршрутов при статической генерации страниц (SSG). С её помощью мы можем указать, какие страницы должны быть сгенерированы на этапе сборки (build-time).

Если вы знакомы с понятием роутинга, представьте, что вам нужно создать страницы для пользователей с различными ID, например /user/1, /user/2, /user/3. getStaticPaths позволяет вам передать список этих ID (или других параметров) на этапе компиляции, чтобы Next.js мог заранее подготовить нужные маршруты.

Основной синтаксис

export async function getStaticPaths() {
  return {
    paths: [
      { params: { id: '1' } },
      { params: { id: '2' } },
    ],
    fallback: false, // Подробнее о fallback чуть ниже
  };
}
  • paths: массив объектов, каждый из которых описывает параметры (например, id) для рендера страницы.
  • fallback: управляет поведением для маршрутов, которые не были включены в paths. Это важно для работы с динамическими страницами.

Пример создания динамических страниц с getStaticPaths

Рассмотрим пример. У нас есть API, предоставляющее список продуктов, и мы хотим сгенерировать страницы для каждого из них. Допустим, API возвращает такой список:

[
  { "id": "1", "name": "Товар 1" },
  { "id": "2", "name": "Товар 2" },
  { "id": "3", "name": "Товар 3" }
]

Шаг 1: создадим динамический маршрут

Динамический маршрут в Next.js создаётся с использованием квадратных скобок в названии файла. Для нашего примера это будет файл pages/product/[id].tsx.

import { GetStaticPaths, GetStaticProps } from 'next';

interface ProductProps {
  id: string;
  name: string;
}

const ProductPage: React.FC<ProductProps> = ({ id, name }) => (
  <div>
    <h1>Продукт: {name}</h1>
    <p>ID: {id}</p>
  </div>
);

export default ProductPage;

Шаг 2: используем getStaticPaths

Теперь добавим логику для получения списка продуктов и генерации маршрутов.

export const getStaticPaths: GetStaticPaths = async () => {
  const res = await fetch('https://example.com/api/products');
  const products: { id: string }[] = await res.json();

  const paths = products.map(product => ({
    params: { id: product.id },
  }));

  return {
    paths, // Генерируем маршруты для каждого продукта
    fallback: false, // Об этом ниже
  };
};

Шаг 3: используем getStaticProps для получения данных

getStaticProps позволяет получить данные для конкретной страницы на этапе сборки.

export const getStaticProps: GetStaticProps = async (context) => {
  const { id } = context.params!;
  const res = await fetch(`https://example.com/api/products/${id}`);
  const product = await res.json();

  return {
    props: {
      id: product.id,
      name: product.name,
    },
  };
};

Теперь любой маршрут вида /product/1, /product/2 и т.д. будет работать!

Типизация возвращаемых данных с помощью TypeScript

Работа с динамическими маршрутами без типизации может привести к хаосу. Рассмотрим, как типизировать данные, возвращаемые в getStaticPaths и getStaticProps.

Типизация getStaticPaths

Сначала создадим интерфейс для описания параметров маршрута:

interface ProductParams {
  id: string;
}

Теперь мы можем указать тип возвращаемых данных в getStaticPaths:

export const getStaticPaths: GetStaticPaths<ProductParams> = async () => {
  const res = await fetch('https://example.com/api/products');
  const products: ProductParams[] = await res.json();

  const paths = products.map(product => ({
    params: { id: product.id },
  }));

  return {
    paths,
    fallback: false,
  };
};

Типизация getStaticProps

Для данных, которые мы получаем из API, тоже создадим интерфейс:

interface ProductData {
  id: string;
  name: string;
}

И применим его в getStaticProps:

export const getStaticProps: GetStaticProps<ProductData> = async (context) => {
  const { id } = context.params as ProductParams;
  const res = await fetch(`https://example.com/api/products/${id}`);
  const product: ProductData = await res.json();

  return {
    props: product,
  };
};

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

fallback: False, True или "blocking"?

Параметр fallback оказывает большое влияние на поведение приложения. Рассмотрим три возможных значения:

fallback: false

Все маршруты, которые не указаны в paths, будут возвращать 404.

  • Подходит для небольших проектов с фиксированным количеством страниц.
  • Каждая страница должна быть предопределена на этапе сборки.

fallback: true

Страницы, не указанные в paths, будут генерироваться при первом запросе.

  • Полезно для больших сайтов с большим количеством страниц.
  • При первом запросе пользователь увидит "заглушку", пока генерируется страница.
export const getStaticPaths = () => ({
  paths: [],
  fallback: true,
});

fallback: 'blocking'

Похож на true, но пользователь будет ждать полной генерации страницы перед её отображением.

  • Идеален для SEO, так как пользователь сразу получает готовую страницу.
export const getStaticPaths = () => ({
  paths: [],
  fallback: 'blocking',
});

Проблемы и особенности

Хотя getStaticPaths мощный инструмент, он может вызвать трудности:

  • Ошибка "Too many pages to generate": если ваш API возвращает слишком много маршрутов, это может замедлить сборку. Решение: используйте fallback: true или blocking.
  • Несогласованные данные: если данные изменились после генерации, пользователи увидят устаревшую информацию. Решение: добавьте функцию revalidate.

Советы по оптимизации

  1. Используйте типизацию данных с TypeScript, чтобы избежать ошибок.
  2. Старайтесь ограничивать список маршрутов для getStaticPaths с помощью пагинации или фильтров.
  3. Спланируйте стратегию работы с fallback в зависимости от ваших требований к производительности и SEO.
export const getStaticProps: GetStaticProps = async (context) => {
  const { id } = context.params!;
  // Добавьте обработку ошибок для недостающих данных
  try {
    const res = await fetch(`https://example.com/api/products/${id}`);
    const product = await res.json();
    if (!res.ok) throw new Error('Error fetching product');

    return {
      props: product,
      revalidate: 10, // Перегенерируйте страницу каждые 10 секунд
    };
  } catch (error) {
    return { notFound: true }; // Верните 404 для отсутствующего продукта
  }
};

Теперь вы знаете, как использовать getStaticPaths для работы с динамическими маршрутами в Next.js. Это позволяет создавать масштабируемые приложения с урезанным временем загрузки. Ну а дальше — ещё больше чудес Next.js!

2
Задача
Модуль 3: React, 14 уровень, 4 лекция
Недоступна
Простое создание маршрутов с getStaticPaths
Простое создание маршрутов с getStaticPaths
3
Опрос
Маршрутизация с Link, 14 уровень, 4 лекция
Недоступен
Маршрутизация с Link
Маршрутизация с Link
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ