When upgrading to React-Router 6 due to some custom architecture around routing and Redux and React-Router removing the Prompt
component I had to go with my custom blocking module that was based on history
package. I created it within useEffect
call as below:
useEffect(() => {
if (shouldBlock) {
const unblock = history.block(transition => {
const url = transition.location.pathname;
openPromptDialog(url, unblock);
});
}
}, [shouldBlock]);
Everything looked like it’s working but I found some minor bug. The openPromptDialog
opens a custom confirm dialog when we want to leave a page with a dirty form (shouldBlock
is true). This part works, but it does not when on the page we save the form and the want to leave. The form is no longer dirty so shouldBlock
is false
however since it used to be true
we didn’t have a chance to unblock it and I can’t find a way to do it.
Please note that I don’t wanna rely on React-Router blocking since I don’t (and can’t at the moment) use Data API createBrowserRouter
which is required in to use useBlocker
.
2
Answers
You can try this to unblock variable is declared outside the if (shouldBlock) block and is accessible in the cleanup function. When the component is unmounted or when shouldBlock changes, the cleanup function will be executed, and it will call unblock if it exists. This ensures that the blocking is properly removed even if shouldBlock becomes false.
The code you have doesn’t ever unblock navigation actions once
shouldBlock
is set true, e.g. like after it is toggled back to false.You can return a cleanup function to unblock navigation actions when the
shouldBlock
dependency updates. This will clean up any previous blockers.Example:
Demo