Ответ
useEffect и useLayoutEffect выполняют схожие задачи, но различаются временем выполнения:
-
useEffect вызывается асинхронно после рендера и отрисовки компонента в DOM. Подходит для сайд-эффектов, не требующих синхронного обновления (запросы, подписки).
-
useLayoutEffect вызывается синхронно после рендера, но перед отрисовкой в браузере. Используется, когда нужно измерить DOM или внести изменения до визуального отображения (например, скролл, анимации).
useEffect(() => {
console.log("Асинхронный эффект");
}, []);
useLayoutEffect(() => {
console.log("Синхронный эффект (перед отрисовкой)");
}, []);
⚠️ useLayoutEffect может блокировать отрисовку, если содержит тяжелые вычисления.
Ответ 18+ 🔞
Давай разберём эту парочку, а то они как близнецы-братья, только один тихий и спокойный, а второй — торопыга, который всё ломает.
Вот смотри, есть у тебя useEffect. Нормальный такой хуёк, воспитанный. Компонент отрендерился, браузер его на экран вывел, все довольны, красота. И только потом, тихонечко, асинхронно, подкрадывается наш эффект и делает свои дела: данные подтягивает, подписки вешает. Никого не дергает, не тормозит. Красота!
useEffect(() => {
console.log("Я как хороший гость — приду, когда всё готово.");
}, []);
А теперь его братан-близнец — useLayoutEffect. Это тот самый родственник, который врывается в квартиру, пока ты ещё дверь открываешь. Компонент только-только посчитался (рендер), но браузер ещё даже пиксели на экран не вывел! А этот уж тут как тут — синхронно, с ноги в дверь, и начинает своё: DOM мерять, стили перекрашивать, скролл прыгать. Всё ДО того, как пользователь что-то увидит.
useLayoutEffect(() => {
console.log("Я уже тут! Быстро давай сюда DOM, мне его щупать надо!");
}, []);
И в этом, блядь, вся соль! Если в useLayoutEffect запихнуть какую-нибудь тягомотину — вычисления овердохуищные, циклы бесконечные — то браузер просто повиснет, ждёт, пока этот торопыга всё своё говно сделает. Пользователь будет смотреть на белый экран и думать: "Ну что, опять эти фронтендеры ебутся?"
Короче, правило простое, как три копейки:
useEffect— для 99% случаев. Запросы, подписки, таймеры — всё, что может подождать микросекунду, пока картинка нарисуется.useLayoutEffect— только когда без этого нихуя. Когда тебе критически нужно что-то поменять в DOM (например, твой тултип позицию посчитать) до того, как юзер моргнёт. Иначе будет дергание, прыгание — пиздец короче.
Запомнил? useEffect — после рисования, useLayoutEffect — до. А то перепутаешь — и волнение ебать, и терпения ноль ебать у всех пользователей.