Using css property "transition: all", I add a dynamic class: (<div className={`${show ? "show" : "hide"}></div> ), but my animation doesn't work

Viewed 94

I am trying to make a Modal component. I would like that when the modal appears, it appears with a transition just like when it disappears. This is currently very jerky, why and how can I fix it?

I would like that when the modal is shown it is shown with an animation and the same behavior when the modal disappears (click on the button).

thank you very much for the help, I know I will learn a lot.

//content of styles.css
.modal {
  position: absolute;
  width: 100%;
  height: 100%;
  background: red;
  transition: all 300ms ease-out;
  transform: translateY(100%);
}

.show {
  transform: translateY(0%);
}

.hide {
  transform: translateY(100%);
}

app.js

import Modal from "./modal";
/*
const Modal = ({ show, children }) => {
 return <div className={`modal ${show ? "show" : "hide"}`}>. 
 {children} </div>;
};
export default Modal;
*/
import ModalContent from "./modalContent";
/*
  const ModalContent = ({ show }) => {
   const showModal = () => {
    show();
   };
  return <button onClick={showModal}> close modal</button>;
};
export default ModalContent;
*/
export default function App() {
 const [show, setShow] = useState(false);
 const closeModal = () => {
  setShow(false);
};

useEffect(() => setShow(true), []);

return (
  <div className="App">
    {show && (
      <Modal show={show}>
        <ModalContent show={closeModal} />
      </Modal>
    )}
  </div>
 );
}

I updated my code:

this is my live code

1 Answers

First of all, in your demo modal disappears immediately, without any transition. It seems, that it's cause by re-rendering of whole App component, on show state change. Extracting Modal component out of App do the trick for me:

const Modal = ({ show, children }) => {
  useEffect(() => {}, [show]);
  return <div className={`modal ${show ? "show" : "hide"}`}>{children} </div>;
};

export default function App() {

Second point - you can't control initial setup just with with css transition. Transition appears when something (class, attribute, pseudoclass) changes on the given element. To get around this and have smooth modal appearance, you can setup one-time useEffect in the App component, which will change show state from false to true. My overall snippet:

const Modal = ({ show, children }) => {
    return <div className={`modal ${show ? "show" : "hide"}`}>{children}        </div>;
};

export default function App() {

const ModalContent = ({ show }) => {
  const showModal = () => {
    show();
  };
  return <button onClick={showModal}> close modal</button>;
};

const [show, setShow] = useState(false);
const closeModal = () => {
  setShow(false);
};

useEffect(() => setShow(true), [])

return (
  <div className="App">
    <Modal show={show}>
      <ModalContent show={closeModal} />
    </Modal>
  </div>
);
}
Related