Зачем нужен hook useLayoutEffect?
Хуки
useLayoutEffect нужен для эффектов, которые должны выполниться до того, как браузер отрисует кадр: измерить DOM и синхронно поправить его, чтобы пользователь не увидел промежуточного состояния.
Место в конвейере
рендер → коммит в DOM → useLayoutEffect → отрисовка кадра → useEffectuseLayoutEffect выполняется синхронно после изменения DOM, но до показа; useEffect — после показа.
Классическая задача: измерить и поправить
const Dropdown = ({ anchorRef }) => {
const [coords, setCoords] = useState(null);
useLayoutEffect(() => {
const rect = anchorRef.current.getBoundingClientRect();
const fitsBelow = rect.bottom + MENU_HEIGHT < window.innerHeight;
setCoords({ top: fitsBelow ? rect.bottom : rect.top - MENU_HEIGHT });
}, [anchorRef]);
if (!coords) return null;
return <ul style={coords}>...</ul>;
};С useEffect меню на один кадр отрисовалось бы не в том месте и «прыгнуло» — мигание. useLayoutEffect выполняет измерение и setState до отрисовки: пользователь сразу видит правильную позицию.
Типичные применения
- Позиционирование тултипов, поповеров, дропдаунов.
- Измерение размеров под условный рендеринг (влезает/не влезает).
- Синхронное восстановление позиции скролла.
- Императивные анимации, стартующие с точного начального состояния.
Почему не использовать всегда
Он блокирует отрисовку: тяжёлая работа в нём — замороженный интерфейс. Правило: по умолчанию useEffect; useLayoutEffect — только при видимых глазом миганиях/прыжкам вёрстки. При SSR на сервере не выполняется (до React 19 React об этом предупреждал, в 19-й версии предупреждение убрали).
Коротко для собеседования
useLayoutEffect выполняется синхронно после коммита DOM, но до отрисовки кадра — для «измерить и поправить» сценариев: позиционирование поповеров, скролл, предотвращение мигания. Блокирует отрисовку, поэтому дефолт — useEffect, а layout-версия — точечно.