Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save michchan/0b142324b2a924a108a689066ad17038 to your computer and use it in GitHub Desktop.
Save michchan/0b142324b2a924a108a689066ad17038 to your computer and use it in GitHub Desktop.
RouteLeavingGuard full implementation in TypeScript & React 16+ for Medium article ca839f5faf39
import { Location } from 'history';
import React, { useEffect, useState } from 'react';
import { Prompt } from 'react-router-dom';
import WarningDialog from './WarningDialog';
interface Props {
when?: boolean | undefined;
navigate: (path: string) => void;
shouldBlockNavigation: (location: Location) => boolean;
}
const RouteLeavingGuard = ({
when,
navigate,
shouldBlockNavigation,
}: Props) => {
const [modalVisible, setModalVisible] = useState(false);
const [lastLocation, setLastLocation] = useState<Location | null>(null);
const [confirmedNavigation, setConfirmedNavigation] = useState(false);
const closeModal = () => {
setModalVisible(false);
};
const handleBlockedNavigation = (nextLocation: Location): boolean => {
if (!confirmedNavigation && shouldBlockNavigation(nextLocation)) {
setModalVisible(true);
setLastLocation(nextLocation);
return false;
}
return true;
};
const handleConfirmNavigationClick = () => {
setModalVisible(false);
setConfirmedNavigation(true);
};
useEffect(() => {
if (confirmedNavigation && lastLocation) {
// Navigate to the previous blocked location with your navigate function
navigate(lastLocation.pathname);
}
}, [confirmedNavigation, lastLocation]);
return (
<>
<Prompt when={when} message={handleBlockedNavigation} />
{/* Your own alert/dialog/modal component */}
<WarningDialog
open={modalVisible}
titleText="Close without saving?"
contentText="You have unsaved changes. Are you sure you want to leave this page without saving?"
cancelButtonText="DISMISS"
confirmButtonText="CONFIRM"
onCancel={closeModal}
onConfirm={handleConfirmNavigationClick}
/>
</>
);
};
export default RouteLeavingGuard;
@parvic1
Copy link

parvic1 commented Sep 8, 2023

Prompt not available in react-router-dom v6. Any thoughts on how to fix?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment