From a library audit (see AUDIT.md on branch claude/library-audit-sxpugz, §3.9).
Motivation
useBlocker's shouldBlock must answer synchronously during the navigate event, which in practice forces window.confirm(). Apps with design systems want a custom modal: block now, ask the user, then proceed or stay.
Proposal sketch
A blocked-state API in the spirit of React Router's useBlocker:
const blocker = useBlocker({ shouldBlock: () => isDirty });
// blocker.state: "unblocked" | "blocked"
// blocker.proceed(): re-run the blocked navigation
// blocker.reset(): stay
Implementation reality check: the Navigation API can't "pause" a navigation — once preventDefault() is called the navigation is dead. So proceed() must replay it (navigation.navigate/traverseTo with the recorded destination, state, info, history mode). Traversals can be replayed with navigation.traverseTo(key). That's exactly the fiddly logic users can't easily write themselves, which makes it worth having in the library. The captured NavigateEvent destination info in the blocker check (packages/router/src/core/NavigationAPIAdapter.ts) has everything needed.
Also worth documenting the limits (some traversals aren't cancelable — see #211, and form submissions would need formData replay or being declared unsupported).
From a library audit (see
AUDIT.mdon branchclaude/library-audit-sxpugz, §3.9).Motivation
useBlocker'sshouldBlockmust answer synchronously during thenavigateevent, which in practice forceswindow.confirm(). Apps with design systems want a custom modal: block now, ask the user, then proceed or stay.Proposal sketch
A blocked-state API in the spirit of React Router's
useBlocker:Implementation reality check: the Navigation API can't "pause" a navigation — once
preventDefault()is called the navigation is dead. Soproceed()must replay it (navigation.navigate/traverseTowith the recorded destination, state, info, history mode). Traversals can be replayed withnavigation.traverseTo(key). That's exactly the fiddly logic users can't easily write themselves, which makes it worth having in the library. The capturedNavigateEventdestination info in the blocker check (packages/router/src/core/NavigationAPIAdapter.ts) has everything needed.Also worth documenting the limits (some traversals aren't cancelable — see #211, and form submissions would need
formDatareplay or being declared unsupported).