← Назад к вопросам

Как реализовать загрузку контента в Suspense?

1.8 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация загрузки контента в React Suspense

React Suspense — это механизм для декларативной обработки состояний загрузки в React-приложениях. Он позволяет компонентам "ожидать" (suspend) данные, промисы или другие ресурсы, пока они не будут готовы к рендерингу. Вот как правильно реализовать загрузку контента с использованием Suspense.

Основные концепции Suspense

Suspense работает в связке с несколькими ключевыми элементами:

  • Компонент Suspense — оборачивает компоненты, которые могут находиться в состоянии загрузки
  • Fallback-проп — компонент, который отображается во время ожидания
  • Ресурсы с поддержкой Suspense — данные или промисы, которые могут "приостанавливать" рендеринг

Практическая реализация

1. Базовый пример с ленивой загрузкой компонентов

import React, { Suspense, lazy } from 'react';

// Ленивая загрузка компонента
const LazyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <div>
      <Suspense fallback={<div>Загрузка компонента...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  );
}

2. Создание ресурсов с поддержкой Suspense

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

// Создаем кэш для ресурсов
function createResource(promise) {
  let status = 'pending';
  let result;
  
  const suspender = promise.then(
    (data) => {
      status = 'success';
      result = data;
    },
    (error) => {
      status = 'error';
      result = error;
    }
  );
  
  return {
    read() {
      if (status === 'pending') {
        throw suspender; // React перехватывает это и показывает fallback
      }
      if (status === 'error') {
        throw result; // Можно обработать через Error Boundary
      }
      return result;
    }
  };
}

// Использование ресурса
const userResource = createResource(fetchUserData());

3. Интеграция с современными библиотеками

Современные библиотеки для управления состоянием имеют встроенную поддержку Suspense:

// Использование с React Query
import { useSuspenseQuery } from '@tanstack/react-query';

function UserProfile({ userId }) {
  const { data } = useSuspenseQuery({
    queryKey: ['user', userId],
    queryFn: () => fetchUser(userId),
  });
  
  return <div>{data.name}</div>;
}

// Обертка в Suspense
function App() {
  return (
    <Suspense fallback={<UserProfileSkeleton />}>
      <UserProfile userId="123" />
    </Suspense>
  );
}

4. Каскадные Suspense и Error Boundaries

import { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';

function Dashboard() {
  return (
    <ErrorBoundary fallback={<ErrorDisplay />}>
      <Suspense fallback={<HeaderSkeleton />}>
        <DashboardHeader />
        
        <Suspense fallback={<ContentSkeleton />}>
          <DashboardContent />
          
          <Suspense fallback={<SidebarSkeleton />}>
            <DashboardSidebar />
          </Suspense>
        </Suspense>
      </Suspense>
    </ErrorBoundary>
  );
}

Ключевые паттерны и лучшие практики

Приоритизация загрузки

Используйте startTransition для разделения срочных и несрочных обновлений:

import { startTransition, Suspense, useState } from 'react';

function SearchComponent() {
  const [query, setQuery] = useState('');
  
  const handleChange = (e) => {
    const value = e.target.value;
    setQuery(value); // Срочное обновление
    
    startTransition(() => {
      // Несрочное обновление с Suspense
      setSearchQuery(value);
    });
  };
  
  return (
    <div>
      <input value={query} onChange={handleChange} />
      <Suspense fallback={<ResultsSkeleton />}>
        <SearchResults query={searchQuery} />
      </Suspense>
    </div>
  );
}

Предзагрузка ресурсов

// Предзагрузка данных до рендеринга
const preloadResource = (url) => {
  const resource = createResource(fetch(url));
  resource.read(); // Начинаем загрузку
  return resource;
};

// Использование в компоненте
const userData = preloadResource('/api/user/123');

Распространенные ошибки и их решение

  1. Отсутствие Error Boundary — всегда оборачивайте Suspense в Error Boundary для обработки ошибок
  2. Неправильное расположение Suspense — Suspense должен находиться выше компонента, который использует ресурс
  3. Избыточные fallback — избегайте вложенных Suspense с одинаковыми fallback

Современные подходы (React 18+)

С React 18 появились новые возможности:

// Streaming SSR с Suspense
import { renderToPipeableStream } from 'react-dom/server';

// Селективные гидратации
<Suspense fallback={<Spinner />}>
  <Comments />
</Suspense>
<Suspense fallback={<Spinner />}>
  <RelatedPosts />
</Suspense>

Заключение

Suspense — это мощная абстракция для управления асинхронными операциями в React. Ключевые преимущества включают декларативный синтаксис, интеграцию с Concurrent Features, и улучшенный UX за счет управляемых состояний загрузки. Для максимальной эффективности комбинируйте Suspense с современными библиотеками данных (React Query, SWR, Apollo) и используйте в связке с Error Boundaries для полноценной обработки всех состояний приложения.