.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("");
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"));