useLayoutEffect для измерений перед анимацией
Используйте useLayoutEffect, чтобы измерить размеры элементов до начала анимации и избежать скачков макета.
«useLayoutEffect для измерений перед анимацией» — бесплатный урок React Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения React Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс React Academy содержит 4 уроков всего.
Проблема мерцания
Иногда при первой отрисовке элемент заметно смещается или мерцает, прежде чем занять нужное положение. Обычно это происходит, когда Вы измеряете или перемещаете элемент после того, как браузер уже отрисовал его.
В течение одного кадра пользователь видит неправильное положение, а затем внезапную коррекцию, из-за чего интерфейс выглядит неисправным.
Почему useEffect вызывает мерцание
useEffect выполняется после отрисовки браузером. Поэтому, если Вы считываете размеры и обновляете DOM внутри useEffect, пользователь уже успевает увидеть нескорректированный кадр до применения изменения.
Для визуального позиционирования, которое должно быть незаметным для пользователя, выполнение после отрисовки происходит слишком поздно.
useLayoutEffect срабатывает до отрисовки
useLayoutEffect синхронно выполняется после того, как React изменит DOM, но до отрисовки браузером. Любое чтение или изменение DOM, выполненное там, применяется до того, как пользователь увидит хотя бы один кадр.
Поэтому этот инструмент подходит для измерений и позиционирования, которые с самого начала должны выглядеть правильно.
Измерение исходного положения
Внутри useLayoutEffect можно получить геометрию элемента с помощью ref.current.getBoundingClientRect(), чтобы зафиксировать его положение и размер перед началом анимации.
Поскольку это выполняется до отрисовки, Вы можете одновременно измерить элемент и применить к нему исходное преобразование без видимого мерцания.
Техника FLIP
FLIP расшифровывается как First, Last, Invert, Play — исходное положение, конечное положение, инверсия и воспроизведение. Сначала Вы фиксируете исходное положение элемента, позволяете ему переместиться в конечное, затем выполняете инверсию, применяя преобразование, которое визуально возвращает его в исходное положение, и наконец запускаете анимацию, убирая это преобразование, чтобы элемент переместился в конечное положение.
Так изменения разметки можно анимировать с помощью одного лишь недорогого transform, даже если настоящая разметка изменилась мгновенно.
getBoundingClientRect в useLayoutEffect
Ключевые измерения выполняются в useLayoutEffect: сохраните геометрию исходного положения до изменения и конечного положения после него, затем вычислите разницу. Выполнение до отрисовки гарантирует, что инвертирующее преобразование будет применено до того, как что-либо появится на экране.
Разница между двумя прямоугольниками даёт точные значения смещения и масштаба для инверсии.
Синхронное применение преобразования
Синхронно установите инвертирующее преобразование внутри useLayoutEffect, а на следующем кадре уберите его, чтобы элемент анимировался в своё естественное положение. Часто для запуска этого шага используют requestAnimationFrame.
Поскольку инверсия применяется до отрисовки, пользователь никогда не видит элемент в его исходном конечном положении.
Предупреждение SSR
На сервере нет DOM, поэтому React записывает в журнал предупреждение о том, что useLayoutEffect ничего не делает во время серверной отрисовки. Эффекты, связанные с разметкой, имеют смысл только в браузере.
Это предупреждение показывает, что эффект не может выполняться там, где нечего измерять.
Безопасная для SSR альтернатива
Если компонент должен выполняться на сервере, используйте useEffect вместе с requestAnimationFrame, чтобы выполнить измерение до следующей отрисовки, либо условно применяйте useLayoutEffect только в браузере.
Так Вы избежите предупреждения и всё же получите для некритичных анимаций время выполнения, близкое к моменту перед отрисовкой.
Пример раскрывающегося аккордеона
Анимация высоты — классический случай: измерьте высоту в свернутом и развернутом состояниях в useLayoutEffect, а затем анимируйте переход между явными значениями в пикселях, чтобы переход был плавным.
Поскольку высота auto не поддерживает анимацию, предварительное измерение реальной высоты позволяет перейти к конкретному числовому значению.
Когда использовать useLayoutEffect
В большинстве случаев по умолчанию используйте useEffect. Применяйте useLayoutEffect только тогда, когда Вы считываете размеры и должны изменить DOM до отрисовки, чтобы избежать видимого мерцания.
Чрезмерное использование этого инструмента может ухудшить производительность, поскольку он блокирует отрисовку до завершения.
Быстрая проверка
Проверьте, насколько хорошо Вы понимаете момент выполнения эффектов.
Итоги
Вы узнали, что проблема мерцания возникает из-за измерения после отрисовки, что useLayoutEffect выполняется до отрисовки и как техника FLIP анимирует изменения разметки с помощью малозатратных преобразований.
Вы также увидели предупреждение SSR и резервный вариант с использованием useEffect и requestAnimationFrame.
Часто задаваемые вопросы
Урок «useLayoutEffect для измерений перед анимацией» бесплатный?
Да — полный текст урока «useLayoutEffect для измерений перед анимацией» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс React Academy, подпишись на CoddyKit PRO. Курс React Academy содержит 4 уроков всего.
Чему я научусь в уроке «useLayoutEffect для измерений перед анимацией»?
Используйте useLayoutEffect, чтобы измерить размеры элементов до начала анимации и избежать скачков макета. Ты практикуешь React Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать React Academy?
Предыдущий опыт не требуется. React Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «useLayoutEffect для измерений перед анимацией»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке React Academy?
Да. Каждый урок React Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Переходы CSS при изменении состояния React
- Анимации CSS с ключевыми кадрами в React
- useLayoutEffect для измерений перед анимацией
- Анимации появления и исчезновения без библиотеки