Вопрос проверяет понимание механизма ре-рендеров в React при передаче пропсов, создаваемых в родительском компоненте, и умение оптимизировать производительность с помощью useMemo, useCallback или React.memo.
В React каждый раз, когда обновляется состояние компонента (например, через setInterval), происходит его ре-рендер. При ре-рендере родителя все дочерние компоненты также перерисовываются по умолчанию, даже если их пропсы не изменились. Это связано с тем, что React не сравнивает пропсы автоматически — он просто вызывает render для всех потомков.
Проблема усугубляется, если в пропсы передаются функции или объекты, создаваемые прямо в JSX. При каждом рендере создаются новые ссылки, что ломает даже React.memo, если не использовать useCallback или useMemo.
Есть три основных подхода:
import React, { useState, useEffect, useCallback, memo } from 'react';
const Child = memo(({ onClick }) => {
console.log('Child re-render');
return <button onClick={onClick}>Click</button>;
});
function Parent() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(timer);
}, []);
// Без useCallback — новая функция каждый рендер
const handleClick = useCallback(() => {
console.log('Clicked');
}, []);
return (
<div>
<p>Count: {count}</p>
<Child onClick={handleClick} />
</div>
);
}В этом примере Child обёрнут в React.memo, а handleClick стабилизирован через useCallback. Благодаря этому Child не будет перерисовываться при каждом тике таймера.
Используйте React.memo для компонентов, которые часто получают одни и те же пропсы, а useCallback/useMemo для стабилизации ссылок. Это особенно важно при работе с таймерами, анимациями или большими списками, чтобы избежать лишних ре-рендеров и сохранить производительность приложения.
Frontend developer
Ментор по Frontend
Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства
Записаться на консультацию