DEV Community

〽️ 𝙍𝙀𝙨𝙝𝙖𝙣
〽️ 𝙍𝙀𝙨𝙝𝙖𝙣

Posted on • Updated on

Open The Modal on click of browser's back button in react (with native javascript)

As React developers, we're always on the lookout for ways to elevate user experience. In this blog post, we'll explore a fascinating challenge: opening a modal when users click the browser's back button in a React application. While React Router v6 offers powerful navigation tools, addressing this specific scenario requires a unique approach.
Let's dive into the details! πŸš€βœ¨

const [confirmModal, setConfirmModal] = useState(false)
Enter fullscreen mode Exit fullscreen mode

First of all we are going to take a State for our Modal, so that we can render our modal.

<CustomModal
  open={confirmModal}
  onClose={closeModal}
  containerStyle={{
    width: "90%",
    maxWidth: "380px",
    minWidth: "380px",
    height: "200px",
    backgroundColor: "#F8F8F8",
  }}
>
  <div
    style={{
      display: "flex",
      width: "100%",
      justifyContent: "center",
      alignItems: "center",
      marginBottom: "20px",
    }}
  >
    <p style={{ fontWeight: "600", fontSize: "16px" }}>
      Confirm cancellation of this transaction?
    </p>
  </div>

  <div className="flex justify-between">
    <div>
      <CustomButton title={"Yes"} onClick={leavePage} />
    </div>
    <div>
      <CustomButton title={"No"} onClick={closeModal} />
    </div>
  </div>
</CustomModal>
Enter fullscreen mode Exit fullscreen mode

We've implemented a straightforward modal, and you can also opt for a regular modal. In my case, I'm using a customModal.

Two functions are required initially to manage the modal. The first one is to close the modal:

const closeModal = () => {
    setConfirmModal(false);
};
Enter fullscreen mode Exit fullscreen mode

We will be using react-router-dom V6,
Initialise it with the following lines:

import {  useNavigate } from "react-router-dom";
const navigate = useNavigate();
Enter fullscreen mode Exit fullscreen mode

We are just simply setting the state to false nothing much,
this function will be used when user clicks on the "YES" Button of our Modal.

const leavePage = () => {
    navigate("/");
};
Enter fullscreen mode Exit fullscreen mode

This function will either push the new URL onto the history stack or replace the current URL

    const urlChangeHandler = (url, replace = false) => {
    const historyMethod = replace ? "replaceState" : "pushState";
    window.history[historyMethod];
  };
Enter fullscreen mode Exit fullscreen mode

Here we are using a arrow function where are making use of a window.history.replaceState method.

In simpler terms, the urlChangeHandler function is like a lookout for changes in the web address (URL). Whenever there's a change, it ensures our application stays updated with the new URL by either adding a new entry to the browser's history or replacing the current one. It's like keeping our app in harmony with what's happening in the browser's address bar.

Now's the time we bring in our javascript functions with useEffect Hook, we cannot use javascript native elements directly in react we need to use them inside the useEffect:

  useEffect(() => {
    urlChangeHandler(window.location.href);
    enterValuesInHiddenInput();

    return () => setConfirmModal(true);
  }, []);
Enter fullscreen mode Exit fullscreen mode

In this code snippet, we are using the urlChangeHandler function to handle the initial URL when the component mounts. We pass the current URL (window.location.href) to this function, effectively setting the URL without adding any extra state. This helps initialise the component's state based on the current URL.

We are calling one more function in the above useEffect, that is enterValuesHiddenInput(),

  const hiddenInputRef = useRef(null);

  const enterValuesInHiddenInput = () => {
    hiddenInputRef.current.onclick;
  };

 <button
  ref={hiddenInputRef}
  style={{visibility: "hidden"}}>
          Test
 </button>

Enter fullscreen mode Exit fullscreen mode

In the above code, we are making use of useRef hook, to run a onclick function to forcefully click the screen and then we are hiding this button.

Additionally, at our clean up function we are setting the state of our modal's state true.

The block of code will trigger the above events whenever user clicks on back button of browser

 useEffect(() => {
    enterValuesInHiddenInput();

    const handlePopState = (event) => {
      event.preventDefault();
      setConfirmModal(true);
    };
    window.addEventListener("popstate", handlePopState);
    window.history.pushState({ modalOpened: false }, "");

    return () => {
      window.removeEventListener("popstate", handlePopState);
    };
  }, [hiddenInputRef, urlChangeHandler]);
Enter fullscreen mode Exit fullscreen mode

The popstate event listener in React is triggered when the browser's history navigation changes. It allows developers to respond to back and forward button clicks, enabling smooth navigation within the application.

In this code, we set up an event listener to detect when the user navigates in the browser. When that happens, we activate the handlePopState function, which sets the confirmModal state to true. This ensures the modal opens when the user interacts with the browser's navigation (e.g., clicks the back button). The cleanup function removes the event listener to prevent issues when the component unmounts.

Now, just call your modal inside

{confirmModal && (
        <CustomModal
          open={confirmModal}
          onClose={closeModal}
          containerStyle={{
            width: "90%",
            maxWidth: "380px",
            minWidth: "380px",
            height: "200px",
            backgroundColor: "#F8F8F8",
          }}
        >
          <div
            style={{
              display: "flex",
              width: "100%",
              justifyContent: "center",
              alignItems: "center",
              marginBottom: "20px",
            }}
          >
            <p style={{ fontWeight: "600", fontSize: "16px" }}>
              Are you sure you want to cancel this transaction?
            </p>
          </div>

          <div className="flex justify-between">
            <div>
              <CustomButton title={"Yes"} onClick={leavePage} />
            </div>
            <div>
              <CustomButton title={"No"} onClick={closeModal} />
            </div>
          </div>
        </CustomModal>
      )}
Enter fullscreen mode Exit fullscreen mode

and with that it's done...

Here's the final Output

Image description

NOTE: before clicking on the browser back button user must interact with the ui first even as small as a click on a screen is enough...

Thank you for reading and Follow me on LinkedIn if you’re interested in Web Development. 😊

Top comments (2)

Collapse
 
tecate profile image
Eli Summers

This is incredible! Thank you for the explanation. I learned a whole ton. :D

Collapse
 
roshan_ican profile image
〽️ 𝙍𝙀𝙨𝙝𝙖𝙣

Thanks a lot also i am sorry that is working but i came across some browser issue when you navigate to the page where you want the modal to open on click of back button then first user needs to interact with the Ui even one click is enough then only the modal will open...