Introduction:
Before reading this article you should know about React Routing, its working.
Main Focus of this post is detecting user leaving page with react-router-dom v6.0.2.
You can use usePrompt or useBlocker to detect and show a prompt before leaving to another route if they have any unsaved changes.
However, in the official documentation of react router v6 the following is mentioned:
from v5 (along with usePrompt and useBlocker from the v6 betas) are not included in the current released version of v6.
But there are two different solution to achieve your goal.
Either you can downgrade to v5 or 6.0.0-alpha.5 to use usePrompt & useBlocker in you project/code
Second solution is create custom hook instead of downgrading.
Post Focus useCallbackPrompt & useBlocker custom hooks
In my today's post I will focus on my second solution how did I created a custom hook to resolve my problem.
for this I created a small project for demo.
Here is the project link GITHUB.
In this project I created two routes for Home and About page and in Home Page there is simple form with Name and Designation Field.
My goal was when user type something on form and trying to leave this page or route prompt/DialogBox will be shown that there are some changes.....
how my folder structure looks like
in above screenshot I highlighted the custom hooks that I created in this project
useBlocker
useCallbackPrompt
useCallbackPrompt Hook
this hooks returns three things 2 boolean variables and 1 function. Basically for handling DialogBox to show or hide
here is the exact file for that useCallbackPrompt Hook
useBlocker Hook
this hook basically blocks user from navigating away if there are any changes
Now Question arise How I am using this in my project
What I am doing here when user type something handleChange will trigger and update the showDialog to true and I am passing showDialog to useCallbackPrompt and when user trying to navigate away a prompt will be shown
Here is Live Demo Link
Here is Git Repo Link
Further improvement, suggestion or help. Welcome :)
Top comments (15)
Small bug:
Make sure to also set the lastLocation to null inside the method cancelNavigation.
Why?
Imagine:
Thanks a lot Muhammad! 🙏🏼
This was extremely helpful. Worked like a charm.
I had to modify useCallbackPrompt a little bit, as it didn't work properly when the component wasn't unmounted after a "confirmed navigation".
The changes are:
[confirmedNavigation, location]
- added location to the handleBlockedNavigation hook. The location object changes and thelocation.pathname
value remains outdated.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.
Thank you Miguel Palacio for fixing :)
Using React Router Dom V6, there is no
navigator.block()
function. use custom history andhistory.block()
function instead, as mentioned in Drew Reese answer on stackoverflowThanks Muhammad for this post. I've been after a nifty solution for this.
One enhancement would be to check if the form value has actually changed, before triggering the dialog? This would mean comparing values in handleChange() and keeping the original form values/states. Any ideas how to implement this?
Hi thanks a lot.
When i click in page reload button, it shows the default browser alertbox. any idea how to solve it?
Having the same issue. Have you made any progress?
Could this be work with some updates if we have a multi-page form? e.g. different pathnames for each step "/form/step1" and "/form/step2"?
can u please give me a solution with react router dom version 6.8.1 ...this code is not working in my case becuase it gives an error that navigator.block is not a function ...can any one help me?
Facing same issue,Did you get any solution.?
I am getting the following error
Any idea how to solve it?
can we have custom popup for browser refresh as well. I tried your code & got the browser default only. Is there a way to show custom message on browser reload?
Could we have custom message in the browser prompt?
I think it's normal to not be able to control everything, it looks like we are not able to add custom functionality to onbeforeunload. developer.chrome.com/blog/chrome-5...
@jaisaro14 @jackwhisler1 @mouerr