React.lazy предоставляет возможность динамической загрузки компонентов в момент их необходимости, что позволяет уменьшить начальный размер бандла и ускорить рендеринг приложения. Этот подход особенно полезен для крупных проектов, где не все компоненты требуются сразу при старте приложения.
Простейший пример использования React.lazy выглядит
так:
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Загрузка...</div>}>
<LazyComponent />
</Suspense>
);
}
export default App;
Здесь ключевые моменты:
React.lazy(() => import('./LazyComponent'))
возвращает компонент, который будет загружен динамически только при
первом рендеринге.<Suspense fallback={...}> позволяет указать
запасной UI (например, спиннер или текст «Загрузка…»), который
отображается до завершения загрузки компонента.При использовании React Router с динамическими импортами важно
оборачивать ленивые компоненты в Suspense. Пример
интеграции с маршрутизацией:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import React, { Suspense } from 'react';
const Home = React.lazy(() => import('./pages/Home'));
const About = React.lazy(() => import('./pages/About'));
const Contact = React.lazy(() => import('./pages/Contact'));
function App() {
return (
<Router>
<Suspense fallback={<div>Загрузка страницы...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</Router>
);
}
export default App;
Особенности:
<Suspense>.fallback может быть любым React-элементом. Часто
используют спиннеры или индикаторы прогресса.В React Router часто применяются вложенные маршруты. С
React.lazy их реализация не отличается по структуре:
const Dashboard = React.lazy(() => import('./pages/Dashboard'));
const DashboardHome = React.lazy(() => import('./pages/DashboardHome'));
const DashboardSettings = React.lazy(() => import('./pages/DashboardSettings'));
function App() {
return (
<Router>
<Suspense fallback={<div>Загрузка...</div>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="" element={<DashboardHome />} />
<Route path="settings" element={<DashboardSettings />} />
</Route>
</Routes>
</Suspense>
</Router>
);
}
Замечания:
Outlet для
отображения содержимого дочерних маршрутов.В реальном приложении загрузка компонентов может завершиться с ошибкой (например, из-за проблем с сетью). Для управления такими ситуациями используют компонент Error Boundary. Пример:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h2>Не удалось загрузить компонент.</h2>;
}
return this.props.children;
}
}
function App() {
return (
<Router>
<ErrorBoundary>
<Suspense fallback={<div>Загрузка...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
</ErrorBoundary>
</Router>
);
}
Особенности:
Suspense для корректного
отображения как состояния загрузки, так и состояния ошибки.const About = React.lazy(() => import('./About'));
About.preload = () => import('./About'); // можно вызвать заранее
<Suspense> как
можно ближе к месту использования.React.lazy и Suspense позволяют построить масштабируемое приложение с маршрутизацией, минимизировать время загрузки и эффективно управлять динамическими компонентами. Правильное сочетание с React Router обеспечивает удобную навигацию без лишней нагрузки на клиент.