Как включить WAAPI в ReactTransitionGroup v2

Я пишу это, предполагая, что читатель уже знает основы React, в основном, как визуализировать компонент и что такое состояние и свойства.

Не стесняйтесь переходить к разделу, начинающемуся с «Вот как это работает», если вы хотите пропустить всю справочную информацию, или до самого конца, чтобы указать ссылку на репо.

Предпосылка: вы хотите изучать анимацию в React масштабируемым и лаконичным способом, демонстрирующим ваше мастерство в пользовательском интерфейсе и дизайне.

Это был я несколько месяцев назад, когда был наивен и идеалистичен.

Поддержка анимации в React в лучшем случае рудиментарна, поскольку не является приоритетом для сторонних разработчиков. Вместо этого у нас есть одна официальная библиотека, поддерживаемая сообществом React (ReactTransitionsGroup), и множество неофициальных дополнительных пакетов, которые подключают сторонние библиотеки к React (например, react-gsap -hancer, react-anime, velocity-response).

После проб и ошибок я не нашел сторонние библиотеки очень гибкими. Некоторые из них не поддерживают важные функции библиотек, к которым они подключены, потому что они все еще находятся в активной (и медленной) разработке. Единственным ответом было использование ReactTransitionsGroup, представлявшего собой сложный API.

(Хотя это может быть просто ужасная документация, которая есть в библиотеке. Например, у нас есть ReactTransitionsGroup v1 здесь. У нас есть ReactTransitionsGroup v2 здесь. Полностью игнорируйте v1. Кстати, документация для v2 это здесь, а v1 и v2 кардинально отличаются. Если вы совершили ту же ошибку, что и я, и начали читать документацию v1, не осознавая, что npm установил v2, вы, вероятно, потеряете волосы, когда ваш код не работа. Как весело.)

Но эта статья должна показать, что мне нужно и мне удалось создать дизайн, который упрощает создание новой анимации и позволяет его масштабировать. (Тем не менее, я не утверждаю, что это хороший код производственного уровня. Продукт, который я кодирую на своей повседневной работе, вообще не имеет анимации.)

Я делаю анимацию с помощью API веб-анимации. Почему именно WAAPI?

Проще говоря: гибкость и производительность.

Что касается JavaScript, у вас есть множество опций, но все они зависят от JavaScript, изменяющего значения внутри атрибута стиля элементов. Это имитация анимации высокого уровня, поэтому она неоптимизирована и отстает от более слабых процессоров.

Между тем, анимация CSS требует жесткого кодирования значений в ваших файлах CSS, что делает их негибкими, когда вы хотите применить ту же анимацию к динамическим элементам. Например, попробуйте заставить много элементов разного размера сжать всю высоту с помощью CSS за 500 мс. Вам нужно будет создать отдельное значение для каждого из них, поскольку возникнут проблемы с масштабированием.

API веб-анимации - единственный, который обеспечивает гибкость JavaScript и оптимизирован. Для меня это достаточно просто, чтобы начать работу менее чем за час, и любой достойный браузер уже будет иметь встроенную поддержку для этого, так что никаких лишних раздутий в ваших репозиториях.

Вот как это работает:

Важными вещами от ReactTransitionsGroup, которые нам нужны, являются Transition и TransitionGroup.

Чтобы анимировать вход или выход из компонента, вы помещаете компонент как дочерний по отношению к компоненту Transition, как показано ниже.

Но если вы это сделаете, у вас возникнут проблемы с обслуживанием кода. Например, если у вас есть компонент, который вы хотите постепенно проявлять и исчезать каждый раз, когда он входит и выходит, вам придется обернуть его вокруг Перехода в каждом месте, где вы используете этот компонент!

Введите компоненты более высокого порядка. Это просто причудливый жаргон React для обозначения функции, возвращающей новый класс, который использует другой. Ниже показан простой пример.

Код преобразуется в это:

Используя переходы, это выглядит так:

Посмотрите его в использовании:

Разве это не хорошо? Теперь мы можем экспортировать компонент более высокого порядка, который обертывает Transition вокруг нашего фактического компонента, и каждое использование InnerComponent во внешних модулях автоматически получает анимацию!

Для финальной части этого дизайна:

Было необходимо создать механизм, позволяющий легко создавать animationProps для передачи в функцию упаковки.

Свойства mountOnEnter unmountOnExit appear enter exit - это просто логические значения, которые Transition принимает, чтобы знать, когда показывать анимацию и нужно ли добавлять или удалять компонент после завершения анимации. (Подробности см. В документации по ReactTransitionsGroup v2).

Свойство Transition addEndListener принимает метод, который принимает node (элемент DOM, который обертывает Transition), и обратный вызов done, который должен быть вызван для обозначения конца анимации.

getAnimationProps - это стандартный метод перезаписи поведения по умолчанию, в основном анимации входа и выхода.

Что касается самих анимаций, node.animate - это метод WAAPI, который принимает то, что эквивалентно ключевым кадрам CSS, но записывается в нотации JavaScript и внутри списка, а также параметры для настройки анимации как второй. onfinish - это свойство, которое хранит обратный вызов, который запускается после завершения анимации, поэтому мы должны вызывать done из endListener внутри него.

В этом случае рабочий процесс для добавления новой анимации так же прост, как создание другого метода, такого как fade, вставка кода WAAPI внутри enterAnimation и exitAnimation и помещения его в качестве параметра animationProps в wrapWithTransition. Нет ничего проще!

Тем не менее, я считаю, что лучший способ понять код - это повозиться с ним и пройти через отладчик, так что вот репо.