Этот вопрос проверяет системный подход к оптимизации производительности React компонентов.
Начну с профилирования производительности React DevTools, затем разделю компонент на меньшие, использую React.memo для предотвращения лишних ре-рендеров, реализую виртуализацию для большого списка, lazy loading для изображений и обработку битых картинок. Также проверю мемоизацию вычислений и оптимизацию обработчиков событий.
Оптимизация большого компонента требует системного подхода и использования специализированных инструментов.
План оптимизации:
1. Анализ и профилирование:
// React DevTools Profiler
// - Запись взаимодействий
// - Поиск "expensive" компонентов
// - Анализ времени рендера
// Chrome DevTools Performance tab
// - Record performance
// - Identify bottlenecks
// - Memory leaks detection2. Разделение компонента:
// Вместо одного большого компонента
const BigComponent = () => {
// 1000 строк кода
};
// Разделить на логические части
const OptimizedComponent = () => (
<>
<Gallery images={images} />
<ItemList items={items} />
<UserPanel user={user} />
</>
);3. Оптимизация ре-рендеров:
// React.memo для предотвращения лишних рендеров
const Gallery = React.memo(({ images }) => {
return images.map(image => (
<Image key={image.id} src={image.url} />
));
});
// useMemo для тяжелых вычислений
const processedItems = useMemo(() => {
return items.map(heavyTransformation);
}, [items]);
// useCallback для стабильных ссылок
const handleClick = useCallback((id) => {
// обработка клика
}, []);4. Виртуализация списка:
// Использование react-window или react-virtualized
import { FixedSizeList as List } from 'react-window';
const VirtualizedList = ({ items }) => (
<List
height={400}
itemCount={items.length}
itemSize={50}
>
{({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
)}
</List>
);5. Оптимизация изображений:
// Lazy loading с Intersection Observer
const LazyImage = ({ src, alt }) => {
const [isVisible, setIsVisible] = useState(false);
const imgRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
setIsVisible(entry.isIntersecting);
});
observer.observe(imgRef.current);
return () => observer.disconnect();
}, []);
return (
<div ref={imgRef}>
{isVisible && <img src={src} alt={alt} />}
</div>
);
};6. Обработка битых картинок:
const ImageWithFallback = ({ src, alt, fallback }) => {
const [hasError, setHasError] = useState(false);
const [currentSrc, setCurrentSrc] = useState(src);
const handleError = () => {
if (!hasError) {
setHasError(true);
setCurrentSrc(fallback);
}
};
return (
<img
src={currentSrc}
alt={alt}
onError={handleError}
loading="lazy"
/>
);
};Инструменты для диагностики:
React DevTools Profiler
Chrome Performance tab
Lighthouse audit
why-did-you-render для отладки ре-рендеров
Приоритеты оптимизации:
Устранение bottlenecks (узких мест)
Снижение количества ре-рендеров
Оптимизация больших списков
Ленивая загрузка контента
Кэширование вычислений