自己实现动效的React弹窗

回到文章
<div id="app"></div>
<div id="modal-container"></div>
.modal{width:200px;height:200px;background-color:#ccc}.fade-enter{opacity:0}.fade-enter-active{transition:opacity 200ms ease-in-out;opacity:1}.fade-enter-done{opacity:1}.fade-exit{opacity:1}.fade-exit-active{opacity:0;transition:opacity 200ms ease-in-out}.fade-exit-done{opacity:0}.zoom-enter{transform:scale(0.3)}.zoom-enter-active{transition:transform 200ms ease-in-out;transform:scale(1)}.zoom-enter-done{transform:scale(1)}.zoom-exit{transform:scale(1)}.zoom-exit-active{transform:scale(0);transition:transform 200ms ease-in-out}.zoom-exit-done{transform:scale(0)}
const { useEffect, useState, createPortal } = React;
const Modal = ({ open, animaionPrefix, children, onClose }) => {
  const [active, setActive] = useState(false); // 弹窗的存在周期
  const [aniClassName, setAniClassName] = useState(""); // 动效的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={classNames("modal", `${animaionPrefix}-${aniClassName}`)} onTransitionEnd={onTransitionEnd}>
      <div className="modal-content">{children}</div>
      <div className="modal-close-btn" onClick={onClose}>
        x
      </div>
    </div>,
    document.getElementById("modal-container")
  );
};

const App = () => {
  const [fadeModalOpen, setFadeModalOpen] = useState(false);
  const [zoomModalOpen, setZoomModalOpen] = useState(false);

  return (
    <div className="app">
      <button onClick={() => setFadeModalOpen(!fadeModalOpen)}>show fade modal</button>
      <button onClick={() => setZoomModalOpen(!zoomModalOpen)}>show zoom modal</button>
      <Modal open={fadeModalOpen} animaionPrefix="fade" onClose={() => setFadeModalOpen(false)}>
        fade modal content
      </Modal>
      <Modal open={zoomModalOpen} animaionPrefix="zoom" onClose={() => setZoomModalOpen(false)}>
        zoom modal content
      </Modal>
    </div>
  );
};
ReactDOM.render(<App />, document.getElementById("app"));