Що робить React.lazy()?
Що робить React.lazy()
React.lazy() дозволяє завантажувати компонент не одразу при старті, а тільки коли він реально знадобиться (наприклад, при переході на сторінку, відкритті модалки тощо).
Синтаксис:
const MyComponent = React.lazy(() => import('./MyComponent'));React.lazy()приймає функцію, що повертає динамічний імпорт (import()).- Цей імпорт повертає Promise, який завантажує JS-файл з компонентом.
- React сам підвантажить компонент, коли дійде до нього в дереві рендера.
Приклад без React.lazy (все вантажиться одразу)
import HeavyChart from './HeavyChart';
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<HeavyChart /> {/* завантажується одразу */}
</div>
);
}Компонент HeavyChart (наприклад, з chart.js або d3) вантажиться одразу,
навіть якщо він не видимий або поки не потрібен.
Стартове завантаження - важке і довге.
Приклад з React.lazy()
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>).
Як це працює "під капотом"
- Коли React зустрічає
<HeavyChart />:
- запускає динамічний імпорт ->
import('./HeavyChart'); - Webpack / Vite створює окремий JS-чанк (наприклад,
HeavyChart.chunk.js).
- Поки чанк завантажується - React показує
fallbackз<Suspense>. - Коли завантаження завершено:
- React рендерить компонент;
- "лінива" частина застосунку стає активною.
Обов'язково обгортати в <Suspense>
React.lazy() працює тільки всередині компонента <Suspense>,
тому що Suspense відповідає за показ "заглушки" під час завантаження:
<Suspense fallback={<Spinner />}>
<LazyComponent />
</Suspense>Без <Suspense> React видасть помилку:
A React component suspended while rendering, but no fallback UI was specified.Приклад лінивого завантаження сторінок (Routing)
Дуже популярний кейс:
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 розділяють код на чанки:
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
Можна заздалегідь "попередньо завантажити" чанк при наведенні, щоб зробити перехід миттєвим:
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: "Не завантажуй цей компонент одразу - підвантаж, коли він знадобиться користувачу."
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.