React implements dynamic pop-up window component

React implements dynamic pop-up window component

When we write some UI components, if we don't consider the animation, it is very easy to achieve. The main thing is to switch the presence or absence (similar to the v-if attribute in Vue) or the visibility (similar to the v-show attribute in Vue).

1. Pop-ups without animation

In React, this can be achieved like this:

interface ModalProps {
  open: boolean;
  onClose?: () => void;
  children?: any;
}
const Modal = ({open.onClose, children}: ModalProps) => {
  if (!open) {
    return null;
  }
  return createPortal(<div>
    <div classname="modal-content">{children}</div>
    <div classname="modal-close-btn" onclick="{onClose}">x</div>
  </div>, document.body);
};

Directions:

const App = () => {
  const [open, setOpen] = useState(false);

  return (
    <div classname="app">
      <button onclick="{()" ==""> setOpen(true)}>show modal</button>
      <modal open="{open}" onclose="{()" ==""> setOpen(false)}>
        Modal content
      </modal>
    </div>
  );
};

Here we use the open attribute to control whether to display or not, but there is no gradient effect at all.

If we want to achieve animation effects such as fade and zoom, we need to modify this.

2. Create animated pop-ups yourself

When many students implement animation effects themselves, they often find that the animation works when it is displayed, but not when it is closed. It’s all because the timing of the animation was not controlled well. Here we first implement the flow of dynamic effects ourselves.

When I first started implementing it, the animation only had a start state and an end state, and it required a lot of variables and logic to control the animation.

Later, I referred to the implementation of react-transition-group component, which split the animation into several parts and controlled each part separately.

  1. The order of expansion animation: enter -> enter-active -> enter-done;
  2. The order of closing animation effects: exit -> exit-active -> exit-done;

The animation process is in the process of enter-active and exit-active .

We use a variable active to control whether the closing animation has been executed, and the parameter open only controls whether the expansion animation or the closing animation is executed.

The popup window is destroyed only when both open and active are false.

const Modal = ({ open, children, onClose }) => {
  const [active, setActive] = useState(false); // Pop-up window existence cycle if (!open && !active) {
    return null;
  }

  return ReactDOM.createPortal(
    <div classname="modal">
      <div classname="modal-content">{children}</div>
      <div classname="modal-close-btn" onclick="{onClose}">
        x
      </div>
    </div>,
    document.body,
  );
};

Here we continue to add changes in the animation process:

const [aniClassName, setAniClassName] = useState(''); // Animation class

// Transition execution completed listening function const onTransitionEnd = () => {
  // When open is rue, the end state is 'enter-done'
  // When open is not false, the end status is 'exit-done'
  setAniClassName(open ? 'enter-done' : 'exit-done');

  // If open is false, the pop-up window's life cycle ends when the animation ends if (!open) {
    setActive(false);
  }
};

useEffect(() => {
  if (open) {
    setActive(true);
    setAniClassName('enter');
    // setTimeout is used to switch classes and make transition happen setTimeout(() => {
      setAniClassName('enter-active');
    });
  } else {
    setAniClassName('exit');
    setTimeout(() => {
      setAniClassName('exit-active');
    });
  }
}, [open]);

The complete code of the Modal component is as follows:

const Modal = ({ open, children, onClose }) => {
  const [active, setActive] = useState(false); // Pop-up window existence cycle const [aniClassName, setAniClassName] = useState(''); // Animation class
  const onTransitionEnd = () => {
    setAniClassName(open ? 'enter-done' : 'exit-done');
    if (!open) {
      setActive(false);
    }
  };

  useEffect(() => {
    if (open) {
      setActive(true);
      setAniClassName('enter');
      setTimeout(() => {
        setAniClassName('enter-active');
      });
    } else {
      setAniClassName('exit');
      setTimeout(() => {
        setAniClassName('exit-active');
      });
    }
  }, [open]);

  if (!open && !active) {
    return null;
  }

  return ReactDOM.createPortal(
    <div classname="{'modal" '="" +="" aniclassname}="" ontransitionend="{onTransitionEnd}">
      <div classname="modal-content">{children}</div>
      <div classname="modal-close-btn" onclick="{onClose}">
        x
      </div>
    </div>,
    document.body,
  );
};

The flow process of the animation has been realized, and the style should also be written together. For example, we want to achieve a fade effect:

.enter {
  opacity: 0;
}
.enter-active {
  transition: opacity 200ms ease-in-out;
  opacity: 1;
}
.enter-done {
  opacity: 1;
}
.exit {
  opacity: 1;
}
.exit-active {
  opacity: 0;
  transition: opacity 200ms ease-in-out;
}
.exit-done {
  opacity: 0;
}

If you want to achieve the zoom effect, just modify these classes.

A pop-up window with animation has been implemented.

Directions:

const App = () => {
  const [open, setOpen] = useState(false);

  return (
    <div classname="app">
      <button onclick="{()" ==""> setOpen(true)}>show modal</button>
      <modal open="{open}" onclose="{()" ==""> setOpen(false)}>
        Modal content
      </modal>
    </div>
  );
};

Click the link to implement your own React pop-up window demo to see the effect.

Similarly, there are Toast and the like, which can also be implemented in this way.

3. react-transition-group

We borrowed the CSSTransition component in react-transition-group to achieve the dynamic effect. CSSTransition has encapsulated the process of dynamic expansion and closing for me. We can directly use this component when implementing pop-up windows.

There is an important property here: unmountOnExit , which means that the component will be uninstalled after the animation ends.

const Modal = ({ open, onClose }) => {
  // http://reactcommunity.org/react-transition-group/css-transition/
  // in property is true/false, true is to expand the animation, false is to close the animation return createPortal(
    <csstransition in="{open}" timeout="{200}" unmountonexit="">
      <div classname="modal">
        <div classname="modal-content">{children}</div>
        <div classname="modal-close-btn" onclick="{onClose}">
          x
        </div>
      </div>
    </csstransition>,
    document.body,
  );
};

After using the CSSTransition component, Modal's animation becomes much more convenient.

4. Conclusion

So far, the React Modal component to be animated has been implemented. Although there is no <transition> tag in React similar to the official definition of Vue, we can implement it ourselves or with the help of third-party components.

The above is the details of how to implement dynamic pop-up window components in React. For more information about React pop-up window components, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • React uses antd's upload component to implement the file form submission function (complete code)
  • Solution to React pure function component setState not refreshing the page update
  • Implementation of React star rating component
  • How to make React components full screen

<<:  Detailed explanation of Dockerfile to create a custom Docker image and comparison of CMD and ENTRYPOINT instructions

>>:  Explanation of the configuration and use of MySQL storage engine InnoDB

Recommend

mysql data insert, update and delete details

Table of contents 1. Insert 2. Update 3. Delete 1...

What are the image file formats and how to choose

1. Which three formats? They are: gif, jpg, and pn...

Detailed explanation of Redis master-slave replication practice using Docker

Table of contents 1. Background 2. Operation step...

Summary of some thoughts on binlog optimization in MYSQL

question Question 1: How to solve the performance...

MySQL 5.7.18 winx64 installation and configuration method graphic tutorial

The installation of compressed packages has chang...

Summary of Commonly Used MySQL Commands in Linux Operating System

Here are some common MySQL commands for you: -- S...

How to simply encapsulate axios in vue

Inject axios into Vue import axios from 'axio...

Nginx stream configuration proxy (Nginx TCP/UDP load balancing)

Prelude We all know that nginx is an excellent re...

Example code for implementing a pure CSS pop-up menu using transform

Preface When making a top menu, you will be requi...

How to view the network routing table in Ubuntu

What are Routing and Routing Table in Linux? The ...

Summary of common operation skills of MySQL database

This article summarizes common operating techniqu...

Detailed process of using nginx to build a webdav file server in Ubuntu

Install nginx Note that you must install nginx-fu...