Check your version
This post assumes you're using React Router v6. If not, find your version below.

As of today, React Router v6 doesn't ship with support for preventing transitions. Once this issue is resolved, we'll update this post with the recommended way to prevent transitions in your app.

For now, here's a very hacky not "approved" approach that "works".

import * as React from "react";
import { UNSAFE_NavigationContext as NavigationContext } from "react-router-dom";
export function useBlocker(blocker, when = true) {
const { navigator } = React.useContext(NavigationContext);
React.useEffect(() => {
if (!when) return;
const unblock = navigator.block((tx) => {
const autoUnblockingTx = {
...tx,
retry() {
unblock();
tx.retry();
},
};
blocker(autoUnblockingTx);
});
return unblock;
}, [navigator, blocker, when]);
}
export default function usePrompt(message, when = true) {
const blocker = React.useCallback(
(tx) => {
if (window.confirm(message)) tx.retry();
},
[message]
);
useBlocker(blocker, when);
}

Now you can usePrompt in your app. usePrompt receives two arguments – when and message. when is a boolean that if true, will show the user a prompt with the message when they try to navigate away.

function Form() {
const [name, setName] = React.useState("");
const [email, setEmail] = React.useState("");
const [note, setNote] = React.useState("");
const isDirty = () => {
return name.length > 0 || email.length > 0 || note.length > 0;
};
usePrompt("Are you sure you want to leave?", isDirty());
return (
<form
onSubmit={(e) => {
e.preventDefault();
alert("Submitted!");
setName("");
setEmail("");
setNote("");
}}
>
...
</form>
);
}

Here's a Codesandbox with the above implementation.

Want to learn more?
If you liked this post and want to learn more, check out our free Comprehensive Guide to React Router.

Before you leave

I know, another newsletter pitch - but hear me out. Most JavaScript newsletters are terrible. When’s the last time you actually looked forward to getting one? Even worse, when’s the last time you actually read one? We wanted to change that.

We call it Bytes, but others call it their favorite newsletter.

Delivered to 109,969 developers every Monday and Thursday