В каких случаях перерисовывается компонент в React?
Компоненты
Компонент перерисовывается в React в четырёх случаях, причём «изменение props» среди них не самостоятельная причина.
Случаи перерисовки
- Обновление собственного state — вызов сеттера useState / dispatch useReducer с новым значением. Если значение то же по
Object.is, React пропустит рендер. - Перерисовка родителя — React по умолчанию рекурсивно рендерит всё поддерево. Ребёнок перерендерится, даже если его props не изменились, если только он не обёрнут в
React.memo. - Изменение контекста — все компоненты с
useContext(Ctx)перерендериваются при изменении value провайдера. - Обновление внешнего стора —
useSelector,useSyncExternalStore, хуки библиотек данных (React Query) триггерят рендер при изменении выбранных данных.
Пример каскада от родителя
const Page = () => {
const [query, setQuery] = useState('');
return (
<>
<SearchInput value={query} onChange={setQuery} />
<Sidebar /> {/* перерендеривается на каждый символ */}
</>
);
};Sidebar не использует query, но перерисовывается — он ребёнок обновившегося компонента.
Что перерисовку НЕ вызывает
- Запись в
ref.current. - Мутация объекта state без новой ссылки — React изменения не увидит.
- Сеттер с тем же значением (Object.is).
Уточнение
Перерисовка (вызов функции компонента) ≠ обновление DOM: после рендера React сравнивает деревья и в DOM вносит только реальные отличия. Лишние рендеры становятся проблемой, когда они частые или дорогие.
Коротко для собеседования
Компонент перерисовывается при: изменении своего state, перерисовке родителя (каскад вниз, останавливается React.memo), изменении потребляемого контекста, обновлении подписки на внешний стор. Рендер — это ещё не DOM-операции: реальные изменения вычисляет reconciliation.