Рубрики
Без рубрики

Как построить многоразовый анимационный компонент с помощью реактивных крюков

Анимации наслаждаются пользователями. И вы бы подумали, что по чистому объему статей, которые реагируют крюки, восхищающие разработчики. Но для меня усталость начинала ползать мне мнения на крючках. Но Serendipity спас меня. Я нашел пример, который был хорошим совпадением для реактивных крюков, а не просто

Автор оригинала: FreeCodeCamp Community Member.

Анимации наслаждаются пользователями. И вы бы подумали, что по чистому объему статей, которые реагируют крюки, восхищающие разработчики. Но для меня усталость начинала ползать мне мнения на крючках.

Но Serendipity спас меня. Я нашел пример, который был хорошим совпадением для реактивных крюков, а не только «нового способа». Как вы, возможно, догадались на название этой статьи, этот пример был анимацией.

Я работал над приложением реагирования с картами в сетке. Когда предмет был удален, я хотел оживить свой выход, как это.

К сожалению, есть нюансы, чтобы сделать эту работу. И мое решение привело меня к хорошему использованию реактивных крюков.

Что мы будем делать?

  • Начните с приложения базового примера
  • постепенно анимировать исчезает элементов, подчеркивая некоторые проблемы
  • Как только мы достигнем желаемой анимации, мы ревертеруемся многоразовой анимационный компонент
  • Мы будем использовать этот компонент для анимирования боковой панели и навбар
  • а также …. (Вам нужно прочитать/прыгать до конца)

Для нетерпеливого, вот Github Repo Для кода в этом проекте. Есть теги для каждого шага. (См. README для ссылок и описаний для каждого тега.)

Базовый

Я создал простое приложение, используя Create-React-App Отказ Он имеет сетку простых карт. Вы можете скрыть отдельные карты.

Код для этого является базовым, и результаты неинтересны. Когда пользователь нажимает глаз Кнопка значка, мы изменяем элемент Дисплей имущество.

function Box({ word }) {
  const color = colors[Math.floor(Math.random() * 9)];
  const [visible, setVisible] = useState(true);
  function hideMe() {
    setVisible(false);
  }
  let style = { borderColor: color, backgroundColor: color };
  if (!visible) style.display = "none";
  return (
    
{" "}
{word}
{" "} {" "}
); }

(Да, я использую крючки выше, но это не интересное использование крючков.)

Добавление анимации

Вместо того, чтобы построить свою собственную библиотеку анимации, я искал библиотеку анимации, как animate.csss Отказ Реактивно-анимированные-CSS хорошая библиотека, которая предоставляет обертку вокруг animate.css.

NPM Установка –Save React-Animated-CSS

Добавить animate.csss к index.html.

В Коробка компонент выше, мы изменяем его рендеринг

return (
  
    
{word}
);

Не совсем то, что мы хотим

Но animate.csss анимает непрозрачность и другие свойства CSS; Вы не можете сделать переход CSS на Дисплей имущество. Таким образом, невидимый объект остается, и он занимает место в потоке документов.

Если вы Google Немного, вы найдете некоторые решения, которые предлагают использовать таймер для установки Дисплей: Нет в конце анимации.

Итак, мы можем добавить это,

function Box({ word }) {
  const color = colors[Math.floor(Math.random() * 9)];
  const [visible, setVisible] = useState(true);
  const [fading, setFading] = useState(false);

  function hideMe() {
    setFading(true);
    setTimeout(() => setVisible(false), 650);
  }

  let style = { borderColor: color, backgroundColor: color };

  return (
    
      
{word}
); }

(Примечание. Продолжительность анимации по умолчанию составляет 1000 мс. Я использую 650 мс для тайм-аута, чтобы минимизировать заикание/паузу, прежде чем настроить свойство Отображение свойство. Это вопрос предпочтений.)

И это даст нам желаемый эффект.

Создание многоразового компонента

Мы могли бы остановиться здесь, но есть две проблемы (для меня):

  1. Я не хочу копировать/вставлять Анимированные блок, стили и функции для воссоздания этого эффекта
  2. Коробка Компонент смешивает различные виды логики, то есть нарушение Разделение опасений Отказ В частности, Коробка Основная функция – сделать карту со своим содержанием. Но детали анимации смешаны.

Компонент класса

Мы можем создать традиционный компонент RACT Class для управления состоянием анимации: переключить видимость и установить тайм-аут для Дисплей Свойство CSS.

class AnimatedVisibility extends Component {
  constructor(props) {
    super(props);
    this.state = { noDisplay: false, visible: this.props.visible };
  }

  componentWillReceiveProps(nextProps, nextContext) {
    if (!nextProps.visible) {
      this.setState({ visible: false });
      setTimeout(() => this.setState({ noDisplay: true }), 650);
    }
  }

  render() {
    return (
      
        {this.props.children}
      
    );
  }
}

а затем использовать его

function Box({ word }) {
  const color = colors[Math.floor(Math.random() * 9)];
  const [visible, setVisible] = useState(true);

  function hideMe() {
    setVisible(false);
  }

  let style = { borderColor: color, backgroundColor: color };

  return (
    
      
{word}
); }

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

Реактивные крючки и использование

Реактивные крючки являются новой особенностью в реакции 16.8. Они предлагают более простой подход к жизненному цикле и управлению государством в компонентах реагирования.

Useffect Крюк обеспечивает элегантную замену нашему использованию ComponentWillReceiveProps Отказ Код проще, и мы можем снова использовать функциональный компонент.

function AnimatedVisibility({ visible, children }) {
  const [noDisplay, setNoDisplay] = useState(!visible);
  useEffect(() => {
    if (!visible) setTimeout(() => setNoDisplay(true), 650);
    else setNoDisplay(false);
  }, [visible]);

  const style = noDisplay ? { display: "none" } : null;
  return (
    
      {children}
    
  );
}

Есть некоторые тонкости с Useffect крюк. Это в первую очередь для побочных эффектов: изменение состояния, вызывая асинхронные функции и т. Д. В нашем случае он устанавливает внутреннюю odisplay логический, основанный на предыдущей ценности Видимый.

Добавляя Видимый на массив зависимостей для Useffect наше Useffect Крюк будет вызван только тогда, когда значение Видимый изменения.

Я думаю Useffect гораздо лучшее решение, чем класс компонент беспорядок. ?

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

Все любят боковые и навкары. Итак, давайте добавим один из каждого.

function ToggleButton({ label, isOpen, onClick }) {
  const icon = isOpen ? (
    
  ) : (
    
  );
  return (
    
  );
}

function Navbar({ open }) {
  return (
    
      
    
  );
}

function Sidebar({ open }) {
  return (
    
      
  • Item 1
  • Item 2
  • Item 3
); } function App() { const [navIsOpen, setNavOpen] = useState(false); const [sidebarIsOpen, setSidebarOpen] = useState(false); function toggleNav() { setNavOpen(!navIsOpen); } function toggleSidebar() { setSidebarOpen(!sidebarIsOpen); } return (
); }

Но мы не сделаны …

Мы могли бы остановиться здесь. Но как с моими предыдущими комментариями о Разделение опасений Я бы предпочел избежать смешивания Анимация невидимость Компонент в методе рендеринга Коробка , Боковая панель ни Навкар Отказ (Это также небольшое количество дублирования.)

Мы можем создать HOC. (На самом деле, я написал статью о анимации и HOCS, Как построить анимированные микроинтехии в React . ) Но HOCS обычно привлечет класс компонентов из-за государственного управления.

Но с реактивными крючками мы можем просто составить HOC (функциональный подход программирования).

function AnimatedVisibility({
  visible,
  children,
  animationOutDuration,
  disappearOffset,
  ...rest
})
// ... same as before
}


function makeAnimated(
  Component,
  animationIn,
  animationOut,
  animationInDuration,
  animationOutDuration,
  disappearOffset
) {
  return function({ open, className, ...props }) {
    return (
      
        
      
    );
  };
}

export function makeAnimationSlideLeft(Component) {
  return makeAnimated(Component, "slideInLeft", "slideOutLeft", 400, 500, 200);
}

export function makeAnimationSlideUpDown(Component) {
  return makeAnimated(Component, "slideInDown", "slideOutUp", 400, 500, 200);
}

export default AnimatedVisibility

а затем используйте эти функциональные HOCS в App.js.

function Navbar() {
  return (
    
  );
}

function Sidebar() {
  return (
    
  • Item 1
  • Item 2
  • Item 3
); } const AnimatedSidebar = makeAnimationSlideLeft(Sidebar); const AnimatedNavbar = makeAnimationSlideUpDown(Navbar); function App() { const [navIsOpen, setNavOpen] = useState(false); const [sidebarIsOpen, setSidebarOpen] = useState(false); function toggleNav() { setNavOpen(!navIsOpen); } function toggleSidebar() { setSidebarOpen(!sidebarIsOpen); } return (
); }

С риском продвижения моей собственной работы я предпочитаю чистый полученный код.

Вот песочница окончательного результата.

Что теперь?

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

Но отдельно от анимации, React Cloots предоставляют возможности создавать читаемый и простой код. Однако есть корректировка мышления. Крючки, как Useffect не являются прямой заменой для всех методов жизненного цикла. Вам нужно будет учиться и экспериментировать.

Я предлагаю смотреть на сайты, такие как usehooks.com и библиотеки, как Воспользуйтесь реагированием , коллекция крючков для различных случаев использования.