Inaara Kalani
Inaara Kalani

Reputation: 476

How to close a modal when user clicks back button?

I am showing user a modal that takes over the entire screen if user is accessing the website on phone. A user tends to instinctively click the back button on their phone to go back to the previous screen instead of using the close button provided on the modal.

Is there a way to intercept the function that is triggered when a user clicks the back button? I want to close the modal when user clicks the back button on their phone, instead of having them redirect to the previous page.

Upvotes: 4

Views: 3467

Answers (3)

Mohammad Dehghani
Mohammad Dehghani

Reputation: 21

Instead of handling the state of modal with useState you should handle it with queryParams

I've created a hook that returns onOpen, onClose, isOpen. You should handle your modal with this hook:

import { useNavigate, useSearchParams } from "react-router-dom";
const useModal = ({ param }: { param: string }) => {
  const [searchParams, setSearchParams] = useSearchParams();
  const navigate = useNavigate();

  const onClose = () => {
    navigate(-1);
  };
  const onOpen = () => {
    searchParams.set("modal", param);
    setSearchParams(searchParams);
  };

  const mySearchParams = searchParams.get("modal");
  const isOpen = mySearchParams === param;

  return { onClose, onOpen, isOpen };
}; 
    
    
  • When you are opening the modal you should call onOpen()
  • When you are closing the modal anywhere in your app you should be calling onClose()

and isOpen is the boolean of is your modal open or not and it returns if you have the exact modal in your url or no

here is how i use it in my component

const { isOpen, onOpen, onClose } = useModal({ param: "test1" });

 <Dialog
      open={isOpen}
      onClose={onClose}
>...

The trick is instead of setting a state to false for closing the modal you need to just navigate(-1)

update:

the syntax has been corrected and "has" method was replaced because in the Old versions of ios it's not supported. thx @DarkBee

Upvotes: 2

Abhishek Kamal
Abhishek Kamal

Reputation: 798

I was on the same issue, so I resolved by using below code :

import React, { useEffect } from 'react';

import { useHistory } from 'react-router-dom';

   const history = useHistory();
    useEffect(() => {
        const unblock = history.block((location, action) => {
            if (isPopupOpen) {
                setIsPopupOpen(false);
                return false; // Prevent navigation
            }
        });

        return () => {
            unblock();
        };
    }, [isPopupOpen, setIsPopupOpen, history]);

Add this code where you wrote the logic of show/hide popup.
It is working for me.

Upvotes: -1

Decelis
Decelis

Reputation: 64

Use the History API. An example on how to acomplish this is:

//listen for state changes
window.onpopstate = (event) => 
{
   if (!event.state.modalOpened)
   {
     closeModal()
   }
}

//change the actual page state so it contains the modalOpened property
window.history.replaceState({modalOpened: false})

function openModal(content) 
{
    //push new state, put the modal information in the state object, this will push a new state, when the user presses the back button, the browser will just trigger the onpopstate event, instead of going to the previous page
    window.history.replaceState({modalOpened: true})

    //this is any code you use to open your modal, for example
    ReactDOM.render(<Modal>{content}</Modal>, document.getElementById("modal-container")
}

class based component

There are many ways to aproach this, this is one of them, everything you need to make something that fits with your app is in the History API DOCS.

//listen for state changes
    window.onpopstate = (event) => 
    {
       if (!event.state.modalOpened)
       {
         updateModal(false, null)
       }
    }

function openModal()
{
//push new state, put the modal information in the state object, this will push a new state, when the user presses the back button, the browser will just trigger the onpopstate event, instead of going to the previous page
        window.history.replaceState({modalOpened: true})
        updateModal(false, <div>Modal content!</div>)
}

function updateModal(open, content)
{
   ReactDOM.render(<Modal open={open} content={content} />, document.getElementById("modal-container")
}

//change the actual page state so it contains the modalOpened property
    window.history.replaceState({modalOpened: false})

class Modal extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    //check the history to determine if we have to open or close the modal
    return <div className={"modal " + (props.open)? "show" : ""}><div className="modal-content">{props.content}</div><button onClick={() => window.history.back()}>OK</button></div>;
  }
}

Upvotes: 1

Related Questions