Capítulo 30 de 57

Chapter 30: Navigation Blocking

Core Idea

Navigation blocking lets you pause or cancel a navigation (both router-controlled and browser-level tab close/refresh) to confirm with the user before discarding unsaved changes, using either useBlocker()/<Block> for custom UI or the browser's native beforeunload dialog.

Key Concepts

  • Blocker Functions: Registered via useBlocker() (hook) or <Block> (component); for router-controlled navigations, blockers run sequentially, returning true allows navigation to proceed, false cancels it.
  • shouldBlockFn: The function passed to determine whether a given navigation attempt should be blocked, based on component/app state (e.g. "form is dirty").
  • current / next: Location objects made available to blocking logic, letting you block conditionally based on where navigation is coming from and going to (e.g. only block leaving a specific route).
  • withResolver: true: Returns proceed() and reset() functions instead of relying on window.confirm(), enabling a custom modal/dialog UI; while blocked, status is 'blocked', and calling proceed() continues the navigation or reset() cancels it.
  • enableBeforeUnload: Conditionally registers the browser's native onbeforeunload handler, which triggers the browser's own default confirmation dialog for uncontrolled events like closing a tab or refreshing, separate from the router-controlled blocker flow.

Key Takeaways

  1. Router-controlled navigations (Link, navigate()) go through the sequential blocker-function flow; uncontrolled browser events (tab close, refresh) are handled separately via enableBeforeUnload and the native dialog, both need to be considered for full unsaved-changes protection.
  2. Use withResolver: true when you want a custom confirmation modal instead of window.confirm(); check status === 'blocked' to render it, and call proceed()/reset() in response to user choice.
  3. shouldBlockFn receiving current/next location lets you scope blocking precisely (e.g. only block navigating away from /edit/* routes) rather than blocking globally.

Connects To

  • Ch 23: Navigation, the ignoreBlocker option on NavigateOptions lets a specific navigation bypass any active blockers.