Skip to main content

Що робить React.lazy()?

Що робить React.lazy()

React.lazy() дозволяє завантажувати компонент не одразу при старті, а тільки коли він реально знадобиться (наприклад, при переході на сторінку, відкритті модалки тощо).


Синтаксис:

javascript
const MyComponent = React.lazy(() => import('./MyComponent'));
  • React.lazy() приймає функцію, що повертає динамічний імпорт (import()).
  • Цей імпорт повертає Promise, який завантажує JS-файл з компонентом.
  • React сам підвантажить компонент, коли дійде до нього в дереві рендера.

Приклад без React.lazy (все вантажиться одразу)

javascript
import HeavyChart from './HeavyChart'; function Dashboard() { return ( <div> <h1>Dashboard</h1> <HeavyChart /> {/* завантажується одразу */} </div> ); }

Компонент HeavyChart (наприклад, з chart.js або d3) вантажиться одразу, навіть якщо він не видимий або поки не потрібен. Стартове завантаження - важке і довге.


Приклад з React.lazy()

javascript
import React, { Suspense, lazy } from 'react'; const HeavyChart = lazy(() => import('./HeavyChart')); function Dashboard() { return ( <div> <h1>Dashboard</h1> <Suspense fallback={<div>Завантаження графіка...</div>}> <HeavyChart /> </Suspense> </div> ); }

Тепер:

  • HeavyChart не входить в основний бандл.
  • React підвантажить його тільки при першому рендері, коли дійде до <HeavyChart />.
  • Поки компонент не завантажений - показується заглушка з fallback (<div>Завантаження...</div>).

Як це працює "під капотом"

  1. Коли React зустрічає <HeavyChart />:
  • запускає динамічний імпорт -> import('./HeavyChart');
  • Webpack / Vite створює окремий JS-чанк (наприклад, HeavyChart.chunk.js).
  1. Поки чанк завантажується - React показує fallback з <Suspense>.
  2. Коли завантаження завершено:
  • React рендерить компонент;
  • "лінива" частина застосунку стає активною.

Обов'язково обгортати в <Suspense>

React.lazy() працює тільки всередині компонента <Suspense>, тому що Suspense відповідає за показ "заглушки" під час завантаження:

javascript
<Suspense fallback={<Spinner />}> <LazyComponent /> </Suspense>

Без <Suspense> React видасть помилку:

javascript
A React component suspended while rendering, but no fallback UI was specified.

Приклад лінивого завантаження сторінок (Routing)

Дуже популярний кейс:

javascript
import { lazy, Suspense } from 'react'; import { Routes, Route } from 'react-router-dom'; const Home = lazy(() => import('./pages/Home')); const Dashboard = lazy(() => import('./pages/Dashboard')); const Settings = lazy(() => import('./pages/Settings')); function App() { return ( <Suspense fallback={<div>Завантаження сторінки...</div>}> <Routes> <Route path="/" element={<Home />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /> </Routes> </Suspense> ); }

Тепер кожна сторінка вантажиться в окремому чанку - тільки коли користувач дійсно заходить на неї.


Що відбувається при збірці

Webpack / Vite розділяють код на чанки:

javascript
main.js Home.chunk.js Dashboard.chunk.js Settings.chunk.js
  • При завантаженні застосунку завантажується тільки main.js.
  • Коли користувач переходить на /dashboard -> React робить GET Dashboard.chunk.js.
  • Таким чином, стартове завантаження стає набагато швидшим.

Коли варто використовувати React.lazy()

Чудово підходить для:

  • сторінок і маршрутів (routing);
  • модальних вікон і діалогів;
  • важких компонентів (таблиці, графіки, редактори, карти);
  • панелей налаштувань і вкладок, які рідко відкриваються;
  • адмінок і SPA, де не все потрібно одразу.

Коли не потрібно використовувати React.lazy()

Надмірне використання може шкодити UX:

  • якщо компонент маленький і легкий - краще вантажити одразу;
  • якщо компонент майже завжди потрібен (наприклад, Header, NavBar);
  • якщо потрібен SSR (серверний рендерінг) - React.lazy() працює тільки на клієнті (потрібні інші рішення, наприклад next/dynamic).

Порівняння "до" і "після"

ПоведінкаБез React.lazy()З React.lazy()
ЗавантаженняВсі компоненти одразуТільки за потреби
Розмір стартового JSВеликийМенший
Стартова швидкістьПовільнішаШвидша
FallbackНемаєЗ'являється під час завантаження
Підтримка SSRЄТільки в клієнтському рендері

Як комбінувати з prefetch/preload

Можна заздалегідь "попередньо завантажити" чанк при наведенні, щоб зробити перехід миттєвим:

javascript
const LazySettings = lazy(() => import('./Settings')); function Nav() { const handleMouseEnter = () => import('./Settings'); // prefetch return <button onMouseEnter={handleMouseEnter}>Налаштування</button>; }

React не буде рендерити компонент одразу, але файл Settings.chunk.js завантажиться заздалегідь.


Підсумок

Що робитьЯк допомагає
Відкладене завантаження компонентівДілить код на чанки
Прискорює завантаження застосункуМенший стартовий JS
Працює з <Suspense>Показує fallback під час завантаження
Простий у використанніconst Comp = lazy(() => import('./Comp'))
Завантажує "за вимогою"Тільки коли компонент реально потрібен

Простими словами:

React.lazy() - це спосіб сказати React: "Не завантажуй цей компонент одразу - підвантаж, коли він знадобиться користувачу."

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.