T
TanStack•16mo ago
flat-fuchsia

Can I listen to unload of a page and conditionally prevent navigation?

I can't find it in the docs, I'd like to know if router currently supports something to show the "you have unsaved data" popup when navigating away from a page (either from navigation or closing the browser window)
9 Replies
other-emerald
other-emerald•16mo ago
Navigation Blocking | TanStack Router React Docs
Navigation blocking is a way to prevent navigation from happening. This is typical if a user attempts to navigate while they: Have unsaved changes
flat-fuchsia
flat-fuchsiaOP•16mo ago
Exactly what I was looking for, thank you! Then a feedback on the search: it wasn't finding it 😄
No description
No description
continuing-cyan
continuing-cyan•16mo ago
Is there a way to display custom UI while blocking navigation? Ideally I'd like to show a custom confirmation dialog, and then proceed with navigation when the confirm button is clicked. It looks like there's no way currently to manually remove the block
flat-fuchsia
flat-fuchsiaOP•16mo ago
If the navigation is performed by the router, you're in full control and can show custom UI (e.g. a user clicks on a button in your app) but if the navigation is triggered outside (e.g. closing the browser tab) then it will take the browser's default
continuing-cyan
continuing-cyan•16mo ago
I managed to make it work with an ugly workaround, but I don't think what I need is achievable with the current implementation. useBlocker here wants a function that returns a boolean, however i'm using that function to display a dialog prompting the user to either stay or navigate. Now, there's no way to tell the router to keep navigating from the dialog itself, when used this way:
useBlocker(
() => setShowModal(true),
form.isValid && form.dirty
)
useBlocker(
() => setShowModal(true),
form.isValid && form.dirty
)
React-router exports a function from the hook that can resume the navigation, and I think that's the key missing here for this pattern.
flat-fuchsia
flat-fuchsiaOP•16mo ago
I haven't tried it yet here so maybe I'm wrong, but I see the first parameter of useBlocker is type type BlockerFn = () => Promise<ShouldAllowNavigation> | ShouldAllowNavigation; I assume you can await a promise there and resolve it only when the user clicks confirm/cancel in your custom UI. That's an interesting topic, I think I'll make a demo on that
continuing-cyan
continuing-cyan•16mo ago
Yeah, this makes sense. However, it'd make more sense if the router exposed a way to do this directly, instead of me having to create a new hook. This is loosely based off the useBlocker implementation https://gist.github.com/freshgiammi/f1f941739ecd62c0037d8a6003eff226 but seems to be working correctly for now, and I can manually handle the promise in a more ergonomic way.
flat-fuchsia
flat-fuchsiaOP•16mo ago
Absolutely, would be much better if this was natively supported in the library. Maybe it's worth creating an issue 😄 (btw you're from Pesaro? I'm from Fano, how tiny the world is 😂)
continuing-cyan
continuing-cyan•16mo ago
haha yeah, what a small world 😆

Did you find this page helpful?