ReactJS - предотвращение начальной анимации модального окна с помощью хуков реакции

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

Modal.js

import React, { useRef, useEffect } from 'react';
import { createPortal } from 'react-dom';

import './Modal.css';

const Modal = ({ isOpen, onClose, children }) => {
  const modalEl = useRef(null);
  const handleCoverClick = (e) => {
    if (e.target.hasAttribute('modal')) {
      onClose();
    }
  }

  useEffect(() => {
    const handleAnimationEnd = (event) => {
      if (!isOpen) {
        event.target.classList.remove('show');
        event.target.classList.add('hide');

      } else {
        event.target.classList.remove('hide');
        event.target.classList.add('show');
      }
    };
    modalEl.current.addEventListener('animationend', handleAnimationEnd);

    return () => modalEl.current.removeEventListener('animationend', handleAnimationEnd);
  }, [isOpen]);

  return createPortal(
    <>
      <div className={`ModalCover ${isOpen ? 'show' : 'hide'}`} onClick={handleCoverClick} modal="true"></div>
      <div className={`ModalContainer ${isOpen ? 'slide-up' : 'slide-down'}`} ref={modalEl}>
        {children}
      </div>
    </>,
  document.body);
};

export default Modal;

Modal.css

.show {
    display: block;
}

.hide {
    display: none;
}

.slide-up {
    transform: translateY(0%);
    animation: slide-up 0.5s forwards;
}

.slide-down {
    transform: translateY(100%);
    animation: slide-down 0.5s forwards;
}

@keyframes slide-up {
    0% { transform: translateY(100%); }
    100% { transform: translateY(0%); }
}

@keyframes slide-down {
    0% { transform: translateY(0%); }
    100% { transform: translateY(100%); }
}

.ModalCover {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
  background-color: rgba(0, 0, 0, 0.15);
}

.ModalContainer {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 400px;
  margin-top: calc(100vh - 400px);
  z-index: 20;
}

демонстрация (codeandbox): https://codesandbox.io/s/l7x5p4k82m

Спасибо!


person REDDY PRASAD    schedule 15.12.2018    source источник
comment
Прочитав ваш пример - вы действительно упускаете возможность не использовать позу реакции popmotion.io/pose, это избавит вас от необходимости писать всю логику класса и анимацию, полагаясь на имена классов css, просто создайте заданный модальный файл и измените его с помощью хука useState. Что касается запуска вашей анимации, просто используйте оператор if внутри хука useEffect или внутри функции анимации дескриптора и не запускайте его после первого рендеринга, используя ваши переменные для оператора if, или объявляйте логическое значение.   -  person Dimitar Nikovski    schedule 17.12.2018


Ответы (1)


Более простой способ - сделать это с помощью classNames, поскольку прямой доступ к DOM не рекомендуется с помощью DOM. modalEl.current ref назначается после первоначального рендеринга, его можно использовать как флаг того, что компонент был смонтирован:

<div className={`
  ModalContainer
  ${isOpen ? 'slide-up' : 'slide-down'}
  ${!modalEl.current && 'hide'}
`} ref={modalEl}>

Применение класса hide к монтированию компонента в useEffect может привести к кратковременному отображению модальной анимации.

person Estus Flask    schedule 15.12.2018
comment
Ваш пример не работает. Вы можете протестировать в codeandbox. я добавил коды и URL-адрес ящика - person REDDY PRASAD; 17.12.2018
comment
Виноват. ваш пример работает нормально. но в моем коде сразу второй раз происходит setState, показывающий анимацию. Спасибо за ответ. - person REDDY PRASAD; 17.12.2018