Reputation: 476
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
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 };
};
onOpen()
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)
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
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
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