DEV Community

Discussion on: Detecting user leaving page with react-router-dom v6.0.2

Collapse
 
miguelpalacio profile image
Miguel Palacio

Thanks a lot Muhammad! 🙏🏼

This was extremely helpful. Worked like a charm.

Collapse
 
miguelpalacio profile image
Miguel Palacio

I had to modify useCallbackPrompt a little bit, as it didn't work properly when the component wasn't unmounted after a "confirmed navigation".

export function useCallbackPrompt(when) {
    const navigate = useNavigate();
    const location = useLocation();
    const [showPrompt, setShowPrompt] = useState(false);
    const [lastLocation, setLastLocation] = useState(null);
    const [confirmedNavigation, setConfirmedNavigation] = useState(false);

    const cancelNavigation = useCallback(() => {
        setShowPrompt(false);
    }, []);

    // handle blocking when user click on another route prompt will be shown
    const handleBlockedNavigation = useCallback(
        (nextLocation) => {
            // in if condition we are checking next location and current location are equals or not
            if (!confirmedNavigation && nextLocation.location.pathname !== location.pathname) {
                setShowPrompt(true);
                setLastLocation(nextLocation);
                return false;
            }
            return true;
        },
        // eslint-disable-next-line react-hooks/exhaustive-deps
        [confirmedNavigation, location]
    );

    const confirmNavigation = useCallback(() => {
        setShowPrompt(false);
        setConfirmedNavigation(true);
    }, []);

    useEffect(() => {
        if (confirmedNavigation && lastLocation) {
            navigate(lastLocation.location.pathname);

            // Clean-up state on confirmed navigation
            setConfirmedNavigation(false);
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [confirmedNavigation, lastLocation]);

    useBlocker(handleBlockedNavigation, when);

    return [showPrompt, confirmNavigation, cancelNavigation];
}

Enter fullscreen mode Exit fullscreen mode

The changes are:

  1. [confirmedNavigation, location] - added location to the handleBlockedNavigation hook. The location object changes and the location.pathname value remains outdated.
  2. setConfirmedNavigation(false); - set after the programmatic navigation, state needed to be cleaned up so that future prompts are displayed.

Sorry if I'm not clear enough. I'm short of time and cannot elaborate a lot. Hopefully it will be useful for someone.

Thanks.

Collapse
 
bangash1996 profile image
Muhammad Bilal Bangash

Thank you Miguel Palacio for fixing :)