Загрузка данных в маршрутах

Загрузка данных в маршрутах — это процесс получения информации (например, с API), необходимой для отображения конкретного экрана. В React Router v6 основной подход заключается в том, что каждый компонент маршрута отвечает за загрузку собственных данных.

Загрузка в компоненте маршрута

Наиболее распространённый способ — инициировать запрос при монтировании компонента, используя useEffect:

// UserProfile.jsx
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';

function UserProfile() {
  const { userId } = useParams();
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => {
        setUser(data);
        setLoading(false);
      });
  }, [userId]);

  if (loading) return <div>Загрузка...</div>;
  return <div>Имя: {user.name}</div>;
}

Каждый маршрут сам управляет своим состоянием загрузки, ошибками и обновлением данных при изменении параметров (например, переходе от /user/1 к /user/2).

Принцип инкапсуляции

Важно, чтобы данные загружались в том компоненте, который их использует. Например, если страница профиля отображает список постов пользователя, запрос к /api/users/:id/posts должен выполняться внутри UserProfile, а не в родительском компоненте. Это:

  • упрощает логику;
  • предотвращает передачу ненужных пропсов;
  • делает компоненты переиспользуемыми.

Альтернатива: loader-функции (React Router v6.4+)

Начиная с версии 6.4, React Router предлагает новый подход — loader-функции, которые выполняются до рендеринга компонента. Они позволяют загружать данные на этапе маршрутизации, а не в самом компоненте:

// routes.js
const userLoader = async ({ params }) => {
  const res = await fetch(`/api/users/${params.userId}`);
  return res.json();
};

<Route path="/user/:userId" element={<UserProfile />} loader={userLoader} />

Однако в рамках текущего курса мы фокусируемся на базовом подходе с useEffect, так как он:

  • работает во всех версиях React Router v6;
  • не требует дополнительной настройки роутера;
  • проще для понимания на начальном этапе.

Рекомендации

  • Не загружайте данные в родительском компоненте ради дочернего — это нарушает инкапсуляцию;
  • Обрабатывайте ошибки загрузки (например, показывайте сообщение при 404 от API);
  • Используйте userId из useParams() как зависимость в useEffect, чтобы обновлять данные при смене параметра.

Этот подход обеспечивает чёткое разделение ответственности и предсказуемое поведение при навигации.