Mohammed Asker
Mohammed Asker

Reputation: 71

Toggle twice to open and close the sidebar menu

In this component, I created a button that will show and hide the sidebar menu. The hiccup is I have to click the button twice to display the sidebar again.

The cause of the problem is probably the overlay className and the useEffect. If I removed the overly className, it may work, but then I won't be able to close the menu by clicking anywhere in the page which is why I included the useEffect codes.

How can I fix this? And is there any helpful tips & resources I can refer to, so that I can avoid the same problem in the future?

const modalRoot = document.getElementById("modal-root");

const Modal = props => {
  return ReactDOM.createPortal(
    <div className="overlay">
      <div className="sidebar-container">{props.children}</div>
    </div>,
    modalRoot
  );
};

export default function App() {
  const [open, setOpen] = React.useState(false);
  useEffect(() => {
    const overlay = document.querySelector(".overlay");
    window.onclick = e => {
      if (e.target === overlay) {
        overlay.style.display = "none";
      }
    };
  });
  return (
    <div className="App">
      <button onClick={() => setOpen(!open)}>Try it</button>
      {open && <Modal in={open}>It works!</Modal>}
    </div>
  );
}

Here's a link for testing the problem: Code Sandbox

Upvotes: 0

Views: 909

Answers (2)

Souki1990
Souki1990

Reputation: 151

It's because you need to setOpen(false) after hiding the modal on your window.click event handler

if (e.target === overlay) {
        console.log(e.target);
        overlay.style.display = "none";
        setOpen(false);
      }

Upvotes: 2

Yatendrasinh Joddha
Yatendrasinh Joddha

Reputation: 222

Here you have to set open false. Please find below change I have made and it is working. Find running demo HERE

  export default function App() {
  const [open, setOpen] = React.useState(false);
  useEffect(() => {
    const overlay = document.querySelector(".overlay");
    window.onclick = e => {
      if (e.target === overlay) {
        overlay.style.display = "none";
        setOpen(!open); // Change is here
      }
    };
  });
  return (
    <div className="App">
      <button onClick={() => setOpen(!open)}>Try it</button>
      {open && <Modal in={open}>It works!</Modal>}
    </div>
  );
}

Upvotes: 1

Related Questions