Open The Modal on click of browser's back button in react (with native javascript)
Tags: javascript, react, hooks, webdev
Published: 2023-12-21 18:08:11

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! 🚀✨


```javascript
const [confirmModal, setConfirmModal] = useState(false)
```

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


```javascript
<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>
```
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:

```javascript
const closeModal = () => {
    setConfirmModal(false);
};
```

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

```javascript
import {  useNavigate } from "react-router-dom";
const navigate = useNavigate();
```

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.

```javascript
const leavePage = () => {
    navigate("/");
};
```


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


```javascript
    const urlChangeHandler = (url, replace = false) => {
    const historyMethod = replace ? "replaceState" : "pushState";
    window.history[historyMethod];
  };
```
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:

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

    return () => setConfirmModal(true);
  }, []);
```
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(),

```javascript
  const hiddenInputRef = useRef(null);

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

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

```

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

```javascript
 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]);
```
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

```javascript
{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>
      )}
```
and with that it's done...

Here's the final Output

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xsl49r8x5tqq9pv04bnj.gif)

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](https://www.linkedin.com/in/roshan-ican/) if you’re interested in Web Development. 😊