I've created a useRouterDisclosure hook to use with modals of my application, where whenever I've to open a modal I push it's key to the hash of the url and to close it, I can simply remove the hash. Doing it this way also handles, back button modal closing on mobile devices and in desktop browsers.
Code:
function useRouterDisclosure({ name, Modal }) {
const { isOpen, onOpen, onClose } = useDisclosure();
const modalQueryKey = `${encodeURIComponent(name)}-modal-state`;
const onToggle = () => {
if (!isOpen) {
window.location.hash = modalQueryKey;
} else {
window.history.back();
}
};
const hashChangeHandler = () => {
const hash = window.location.hash;
const hashVal = hash.length ? hash.split('#')[1] : '';
console.log('hash handler: ', isOpen, name);
if (!isOpen && hashVal === modalQueryKey) {
console.log('opening: ', name);
onOpen();
}
if (isOpen && hashVal !== modalQueryKey) {
console.log('closing: ', name);
onClose();
}
};
useEffect(() => {
window.addEventListener('hashchange', hashChangeHandler);
return () => {
window.removeEventListener('hashchange', hashChangeHandler);
}
}, []);
const Component = (props) => (
!!isOpen && <Modal isOpen={isOpen} onClose={onToggle} {...props} />
);
return [onToggle, Component];
};
Due to some reason, the updated value of isOpen is not reflected in hashChangeHandler and hence the modal never closes because isOpen is always false. What could be the possible reasons for it and how to handle it?