Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# React.lazy: Ленивая загрузка компонентов
React.lazy — это функция, которая позволяет вам импортировать компоненты динамически и загружать их только когда они действительно необходимы. Это критически важный инструмент для оптимизации производительности приложений, особенно при работе с большими приложениями.
Базовое использование
// Обычный импорт
import HeavyComponent from './HeavyComponent';
// С React.lazy — динамический импорт
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
Когда вы используете React.lazy, компонент загружается только при первой попытке его отобразить. Это особенно полезно для компонентов, которые не используются сразу при загрузке страницы.
Как это работает
import React, { Suspense } from 'react';
// Ленивая загрузка компонента
const Dashboard = React.lazy(() => import('./pages/Dashboard'));
const Settings = React.lazy(() => import('./pages/Settings'));
const Profile = React.lazy(() => import('./pages/Profile'));
function App() {
const [page, setPage] = React.useState('dashboard');
return (
<div>
<nav>
<button onClick={() => setPage('dashboard')}>Dashboard</button>
<button onClick={() => setPage('settings')}>Settings</button>
<button onClick={() => setPage('profile')}>Profile</button>
</nav>
<Suspense fallback={<div>Loading...</div>}>
{page === 'dashboard' && <Dashboard />}
{page === 'settings' && <Settings />}
{page === 'profile' && <Profile />}
</Suspense>
</div>
);
}
Suspense: обработка загрузки
React.lazy ВСЕГДА используется с компонентом Suspense, который позволяет отобразить fallback контент во время загрузки:
function App() {
return (
<Suspense fallback={<LoadingSpinner />}>
<LazyComponent />
</Suspense>
);
}
// fallback может быть любым React компонентом
const LoadingSpinner = () => (
<div className="spinner">
<p>Загружается...</p>
</div>
);
Вложенные Suspense границы
function App() {
return (
<div>
<Header />
<Suspense fallback={<HeaderSkeleton />}>
<UserInfo />
</Suspense>
<Suspense fallback={<MainSkeleton />}>
<MainContent />
</Suspense>
<Suspense fallback={<SidebarSkeleton />}>
<Sidebar />
</Suspense>
</div>
);
}
Вложенные Suspense границы позволяют более гранулированно контролировать загрузку разных частей приложения.
Реальные примеры использования
Маршрутизация с React Router
import { BrowserRouter, 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 (
<BrowserRouter>
<Suspense fallback={<div>Loading page...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Модальные окна
const EditUserModal = React.lazy(() => import('./modals/EditUserModal'));
const DeleteConfirmModal = React.lazy(() => import('./modals/DeleteConfirmModal'));
function UserManagement() {
const [showEdit, setShowEdit] = React.useState(false);
const [showDelete, setShowDelete] = React.useState(false);
return (
<>
<button onClick={() => setShowEdit(true)}>Edit</button>
<button onClick={() => setShowDelete(true)}>Delete</button>
{showEdit && (
<Suspense fallback={<div>Loading modal...</div>}>
<EditUserModal onClose={() => setShowEdit(false)} />
</Suspense>
)}
{showDelete && (
<Suspense fallback={<div>Loading modal...</div>}>
<DeleteConfirmModal onClose={() => setShowDelete(false)} />
</Suspense>
)}
</>
);
}
Условная загрузка компонентов
const AdminPanel = React.lazy(() => import('./AdminPanel'));
const UserDashboard = React.lazy(() => import('./UserDashboard'));
function App({ isAdmin }) {
return (
<Suspense fallback={<div>Loading...</div>}>
{isAdmin ? <AdminPanel /> : <UserDashboard />}
</Suspense>
);
}
Обработка ошибок при загрузке
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <div>Ошибка при загрузке компонента</div>;
}
return this.props.children;
}
}
const LazyComponent = React.lazy(() => import('./Heavy'));
function App() {
return (
<ErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</ErrorBoundary>
);
}
Ограничения и важные моменты
- Только для компонентов по умолчанию — React.lazy работает только с компонентами, которые экспортируются как
export default:
// ✅ Работает
export default function MyComponent() {}
const LazyComp = React.lazy(() => import('./Component'));
// ❌ Не работает
export function MyComponent() {}
const LazyComp = React.lazy(() => import('./Component')); // Ошибка!
- Code splitting — React.lazy автоматически создаёт отдельные бандлы для загруженных компонентов
- Производительность — улучшает начальную загрузку, но добавляет задержку при отображении компонента
- Network условия — важно иметь хорошую fallback UI для медленных сетей
Производительность и метрики
const HeavyChart = React.lazy(
() => import(/* webpackChunkName: "chart" */ './HeavyChart')
);
const HeavyEditor = React.lazy(
() => import(/* webpackChunkName: "editor" */ './HeavyEditor')
);
Средняя экономия на начальной загрузке при использовании React.lazy — 20-40% в зависимости от размера приложения.