I have created a custom React Router Prompt to show when the user wants to navigate to other page and have not saved the data yet.
Everything seems to be working as it should, but I have an annoying warning:
Warning: A history supports only one prompt at a time
The component looks like this:
export function RouterPrompt(props) {
const {when, onOK, onCancel, title} = props;
const history = useHistory();
const [showPrompt, setShowPrompt] = useState(false);
const [currentPath, setCurrentPath] = useState("");
useEffect(() => {
if (when) {
history.block((prompt) => {
setCurrentPath(prompt.pathname);
setShowPrompt(true);
return "true";
});
} else {
history.block(() => {
});
}
}, [when]);
const handleOK = useCallback(async () => {
if (onOK) {
const canRoute = await Promise.resolve(onOK());
if (canRoute) {
history.block(() => {
});
history.push(currentPath);
}
}
}, [currentPath, history, onOK]);
const handleCancel = useCallback(async () => {
if (onCancel) {
const canRoute = await Promise.resolve(onCancel());
if (canRoute) {
history.block(() => {
});
history.push(currentPath);
}
}
setShowPrompt(false);
}, [currentPath, history, onCancel]);
return showPrompt ? (
<Dialog
open={showPrompt}
onClose={handleCancel}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{title}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
There are unsaved changes. Are you sure want to leave this page?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleCancel}>Stay on page</Button>
<Button onClick={handleOK} autoFocus>
Leave
</Button>
</DialogActions>
</Dialog>
) : null;
}
As far as I was able to do some research on this, this comes from the class lifecycle methods (useEffect runs before unmouting the current history.block), but in reality only one Prompt is rendered in the DOM.
Edit
I have discovered another bug, that this will change the path regardless of the actual push or not. So in the URL the path changes but the view don't, so next time when you press back and Confirm, instaed of staying on the page, you will be 2 steps back in history.