How do I prevent leave route?
Thanks for the nimble navigation project. I am considering use navi instead of react-router in next project.
I want to redirect new user with initial password to change_password_page and prevent it leave the page before password changed. I can't find the impl in navi, can you help to figure out how make it works with navi?
One possibility would be to put the user details in context, and then use a top-level map. Something like this:
mount({
'/change-password': lazy(() => import('./change-password')),
'*': map(request => {
if (request.context.requiresPasswordChange) {
return redirect('/change-password?redirectTo='+encodeURIComponent(request.url.href), { exact: false })
}
else {
return routes
}
})
})
@jamesknelson Thanks for your reply.
I need custom dialog to prompt user to change password first when he clicked other links to redirecting.
I dig into source code then I think maybe there should add some methods in Navigation class:
navigation.prototype.beforeLeave = (callback) => {
this._beforeLeaveCheck = callback
const allowed = this._beforeLeaveCheck()
if (!allowed) this._history.block()
else this._history.unblock()
return unsubscriber(this._beforeLeaveCheck)
}
then use it like:
useEffect(() => {
const check = () => {
if (context.user.requiredPasswordChanged) {
customDialog.show()
return false
}
return true
}
return navigation.beforeLeave(check).unsubscribe
}, [])
I need the same functionality. I need to prompt a user to save before navigating away. It needs to happen before the component unmounts.
Nevermind. Redirecting back to the original component works. I had something in the component watching the route that caused it to re-render.
Can we add a navigation.pause() method that sets the context within navi?
@JacksonGariety that sounds like an interesting solution. Could you explain in a little more detail what navigation.pause() would be supposed to do?
I didn't get how to not leave the route. I want to make any form to be able to cancel any route change request.
So I put for example { unsavedData: true } into context and.. then what? How to cancel route transition?
As far as I understand I cannot return null or false or undefined from map(). Nor can I retrieve the current route from within map().
"*": map(async (request, context: RouterContext) => {
// Check for unsaved data
const unsaved = context.store.getState().app.unsavedData;
if (unsaved) {
// <<<<<<< How to prevent navigating to the requested route? How to CANCEL it? >>>>>>
}
...
Nevermind. Redirecting back to the original component works. I had something in the component watching the route that caused it to re-render.
So you couldn't solve this task in the router, did you?
I tried saving current route in the state but it didn't help too.
Say my current route is /profiles/3/edit which is a profile editing form.
When the form gets changed I set app.unsavedData flag in the state and store the current route in app.currentRoute:
"*": map(async (request, context: RouterContext) => {
// Check for unsaved data
const unsaved = context.store.getState().app.unsavedData;
if (unsaved) {
const currentRoute = context.store.getState().app.currentRoute; // == /profiles/3/edit
return redirect(currentRoute);
}
Now if I click say /profiles/2 link, instead of following to the /profiles/3/edit according to the redirect() (i.e. staying where it was), it now returns 404 for the new route:
NotFoundError: URL not found: /profiles/2
/profiles/2 actually does exist but for some reason it doesn't go there or stay where it was on /profiles/3/edit.
@jamesknelson Do you have any idea? Navi is so powerful and asynchronous and flexible, I believe there should be a way to cancel a mere transition.
@jamesknelson ?
ping @jamesknelson
Dear James.
Would you please have a look at this thread and share your vision? In my humble opinion, this is very important part of the routing to be able to cancel transition.
ping @jamesknelson
Perhaps it should simply mimic the browser's beforeunload event. So navi should expose a method to set and unset a confirmation string, and then navi should display that confirmation string before navigating away from the route.
No, not just beforeunload. If you click "back" or "forward" button in browser's navigation bar, NO EVENT could let you cancel the history pop.
On Mon, Dec 7, 2020 at 04:27 clmn [email protected] wrote:
Perhaps it should simply mimic the browser's beforeunload event. So navi should expose a method to set and unset a confirmation string, and then navi should display that confirmation string before navigating away from the route.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/frontarm/navi/issues/93#issuecomment-739558683, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACWRBA2AWSMERSO6LRAJTLTSTPSLDANCNFSM4HQK6EAQ .
Hi, is there any update on this? It still is an issue.
Edit:
One solution that I found working in a React app is to use the history.block function. You can access the history object using the useHistory() hook. Here's a little snippet:
const history = useHistory();
useEffect(() => {
history.block(() => {
if (condition) {
return "Your prompt message";
}
});
}, [condition]);
Thanks @lukaszromerowicz. I will try it later.