Как использовать React.lazy и Suspense?react-56

React.lazy и Suspense — это две взаимодополняющие API, которые позволяют реализовать ленивую загрузку (lazy loading) компонентов в React-приложениях. Рассмотрим их использование подробно.

1. Базовый синтаксис

import { lazy, Suspense } from 'react';

const LazyComponent = lazy(() => import('./LazyComponent'));

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

2. Как это работает

  1. React.lazy:

    • Принимает функцию, которая вызывает динамический import()
    • Возвращает новый компонент, который загружается лениво
    • Работает только с default экспортами
  2. Suspense:

    • Позволяет показать запасной контент (fallback) во время загрузки
    • Может обрабатывать несколько ленивых компонентов одновременно
    • Отлавливает состояние "подвешивания" (suspending)

3. Ленивая загрузка маршрутов

Чаще всего используется с React Router:

import { Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));

function App() {
  return (
    <Suspense fallback={<GlobalLoader />}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  );
}

4. Обработка ошибок

Обязательно сочетайте с Error Boundary:

import { ErrorBoundary } from 'react-error-boundary';

function ErrorFallback({ error }) {
  return (
    <div role="alert">
      <p>Ошибка загрузки компонента:</p>
      <pre>{error.message}</pre>
    </div>
  );
}

<ErrorBoundary FallbackComponent={ErrorFallback}>
  <Suspense fallback={<Loader />}>
    <LazyComponent />
  </Suspense>
</ErrorBoundary>

5. Именованные экспорты

Для компонентов с именованным экспортом:

const LazyComponent = lazy(() =>
  import('./LazyComponent').then(module => ({
    default: module.LazyComponent
  }))
);

6. Предзагрузка компонентов

Для улучшения UX можно предзагружать компоненты:

const LazyComponent = lazy(() => import('./LazyComponent'));

// Предзагрузка при наведении или других событиях
function handleMouseEnter() {
  import('./LazyComponent');
}

function App() {
  return (
    <div onMouseEnter={handleMouseEnter}>
      <Suspense fallback={<Loader />}>
        <LazyComponent />
      </Suspense>
    </div>
  );
}

7. Несколько Suspense границ

Можно создавать вложенные Suspense с разными fallback:

<Suspense fallback={<AppLoader />}>
  <Header />
  <Suspense fallback={<SidebarLoader />}>
    <Sidebar />
  </Suspense>
  <MainContent>
    <Suspense fallback={<ContentLoader />}>
      <LazyComponent />
    </Suspense>
  </MainContent>
</Suspense>

8. Webpack Magic Comments

Используйте комментарии для webpack:

const LazyComponent = lazy(() => import(
  /* webpackChunkName: "lazy-component" */
  /* webpackPrefetch: true */
  './LazyComponent'
));

Ограничения

  1. Не работает с SSR в чистом React (в Next.js используйте dynamic imports)
  2. Требует Suspense для обработки состояния загрузки
  3. Только default экспорты в базовом варианте
  4. Нет контроля над загрузкой после инициализации

Резюмируем

React.lazy и Suspense предоставляют простой способ реализации ленивой загрузки:

  • Используйте React.lazy для динамических импортов компонентов
  • Обязательно оборачивайте в Suspense с fallback
  • Сочетайте с Error Boundary для обработки ошибок
  • Применяйте для маршрутов и тяжелых компонентов
  • Используйте предзагрузку для улучшения UX

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