Разница между useEffect и useLayoutEffect — объяснено на реальном примере.
В чем разница между двумя хуками React (useEffect и useLayoutEffect)с одинаковой подписью, похожими именами и похожими результатами? Лучше один раз увидеть разницу между ними, чем тысячу раз прочитать об этом! 🦉
На рисунке ниже показаны два окна чата — после загрузки страницы сообщения «извлекаются», а затем каждое окно чата прокручивается вниз. В левом поле используется хук useLayoutEffect для прокрутки вниз, а в правом — useEffect. Вы можете заметить какое-то странное мигание только в правом поле, используя useEffect. Но почему? 🤷♂️

Примечание. GIF-файл выше взят из приложения, использующего React v17. Мы будем использовать это для сравнения, чтобы позже увидеть другое поведение в React v18+.
Разница между useLayoutEffect и useEffect
Чтобы понять, почему пользовательский интерфейс мигает, нам нужно сначала понять разницу между двумя хуками. Разница между useLayoutEffect и useEffect заключается в том, когда срабатывают хуки. Это лучше всего видно в контексте жизненного цикла компонента React:
Жизненный цикл компонента React
- Пользователь взаимодействует с приложением и изменяет состояние или реквизиты компонента.
- React обновляет объектную модель документа (DOM).
- Срабатывает хук
useLayoutEffect. - Браузер отрисовывает => пользователю отображаются визуальные изменения.
- Срабатывает хук
useEffect.
Почемуприложение React мерцает только при использовании useEffect
Обратите внимание, что useLayoutEffect срабатывает до того, как браузер начнет рисовать и пользователь увидит какие-либо визуальные изменения. По сути, это секрет того, как избежать мерцания.
Если вы используете хук useEffect для прокрутки вниз, он срабатывает только после того, как сообщения уже были показаны пользователю (см. жизненный цикл компонента), и это вызывает мерцание. С другой стороны, если вы используете хук useLayoutEffect, сначала сообщения добавляются в DOM, затем сообщения прокручиваются вниз путем мутации DOM, и только после этого пользователю представляются визуальные изменения (без мерцания).
Когда лучше использовать LayoutEffect
Если вам нужно напрямую обновить DOM и внести визуальные изменения в пользовательский интерфейс, вы должны использовать useLayoutEffect. Это делает его более плавным и устраняет проблемы с мерцанием.
Различное поведение useEffect в React 17 и React 18
В предыдущем примере показано, что происходит при начальной загрузке сообщений. Однако, начиная с React 18, поведение может отличаться, если реквизиты или состояние компонента изменяются в результате пользовательского ввода, такого как щелчок.
В React 17(gif ниже) вы по-прежнему можете наблюдать ту же проблему мерцания, если пользователь добавляет сообщение, нажав кнопку, а вы используете useEffect для прокрутки.

С React 18 (gif ниже) вы получаете плавную прокрутку «бесплатно» даже с useEffectесли пользователь добавляет новое сообщение, нажав кнопку. Это еще одна причина, по которой вам следует обновлять пакеты npm.

Заключение
Хуки useEffect и useLayoutEffect React имеют одинаковую сигнатуру и оба используются для побочных эффектов. Разница в том, когда они стреляют. Хук useLayoutEffect срабатывает до того, как браузер отрисует (до того, как пользователь увидит визуальные изменения). Хук useEffect срабатывает после того, как браузер рисует. Вы должны использовать useLayoutEffect, когда вы напрямую обновляете DOM, чтобы избежать мерцания. Кроме того, не забывайте обновлять пакеты npm и другие инструменты, чтобы получить от них максимальную отдачу.
Если вам понравилась эта статья, подпишитесь на меня, чтобы получать дальнейшие советы по разработке с помощью React, JavaScript, TypeScript и т. д.! 🚀

GitHub
Вы можете найти приложение React, используемое для гифок, в этой статье на GitHub. Не стесняйтесь экспериментировать с хуками и различными версиями React! 💪
Становиться участником
Если вам нравится читать такие истории и вы хотите поддержать меня как автора, подумайте о том, чтобы зарегистрироваться, чтобы стать участником Medium. Это $5 в месяц, что дает вам неограниченный доступ к историям на Medium. Если вы зарегистрируетесь по моей ссылке, я получу небольшую комиссию🙌
Вакансия - Присоединяйся ко мне
Моя замечательная команда в Tjekvik ищет новых разработчиков! У вас есть опыт работы с React и Ruby on Rails? Тогда не раздумывайте и подавайте заявку прямо здесь: https://www.tjekvik.com/careers. Вы можете работать из любой точки Европы! 🌍
Откажитесь от использования «&& для условного рендеринга в React
Избегайте ошибок, не используя `&&` в компонентах Reactjakub-kozak.medium.com»
Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord.