ReactJS - 使用反应钩子防止模态的初始动画

Posted

技术标签:

【中文标题】ReactJS - 使用反应钩子防止模态的初始动画【英文标题】:ReactJS - Prevent initial animation of modal with react hooks 【发布时间】:2019-05-16 09:18:39 【问题描述】:

我构建了一个简单的 Modal 组件,它在打开时会从底部滑动。单击模态触发按钮并单击背景时,动画效果很好。但是我在页面的初始渲染中看到了向下滑动的动画。我怎样才能防止初始动画?我正在专门研究如何使用 react hooks 来解决。

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;

演示(代码沙盒):https://codesandbox.io/s/l7x5p4k82m

谢谢!

【问题讨论】:

已经阅读了你的例子——你真的错过了不使用 react-pose popmotion.io/pose,它可以让你不必编写所有的类逻辑和动画并依赖 css 类名,只是创建一个姿势模态并通过 useState 钩子更改它。在运行动画方面,只需在 useEffect 钩子或句柄动画函数中使用 if 语句,并且不要在第一次渲染后使用 if 语句的变量或声明布尔值来运行它。 【参考方案1】:

更简单的方法是使用classNames 执行此操作,因为不鼓励使用 DOM 直接访问 DOM。 modalEl.current ref 是在初始渲染后分配的,它可以用作组件已挂载的标志:

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

useEffect 中的组件挂载上应用hide 类可能会导致简要显示模态动画。

【讨论】:

您的示例不起作用。您可以在代码沙盒中进行测试。我添加了代码框网址 我的错。你的例子工作正常。但在我的代码中,第二次立即发生 setState 并显示动画。感谢您的回答。

以上是关于ReactJS - 使用反应钩子防止模态的初始动画的主要内容,如果未能解决你的问题,请参考以下文章

反应原生模态时间延迟和生涩的动画

创建钩子时真的需要导入'React'吗? (反应钩子)

如果响应在模态中出错,则 ReactJS 引导警报

为啥在反应的“useState”钩子中一遍又一遍地设置初始状态

删除模态。反应 Redux。无法读取未定义的属性“_id”

SwiftUI:自定义模态动画