---
id: navigation-blocking
track: learn
product: router
locale: en
order: 12
revision: 2
sourceCheckedOn: "2026-08-03"
versionRange: "Router ^1"
verifiedAgainst: "@tanstack/react-router@1.170.18"
contentModel: 2
prerequisites:
  - "Controlled React forms and Router navigation basics"
sourceRefs:
  - "https://tanstack.com/router/latest/docs/guide/navigation-blocking"
---

# Block navigation away from a dirty form

> Use useBlocker for router navigation and browser unloads, with explicit state for a custom confirmation UI.

**Outcome:** Register a blocker only for unsaved changes and correctly connect proceed, stay, and tab-closing behavior.

## Derive blocking from real dirty state

Returning true from shouldBlockFn blocks navigation. enableBeforeUnload covers browser-level refreshes and tab closes; enable it only while isDirty is true so clean pages do not prompt users.

## Custom confirmation needs a resolver

With withResolver: true, render confirmation when status becomes blocked. proceed allows the navigation and reset keeps the current page. Clear dirty state after a successful save so later navigation is not blocked by stale state.

> **Note:** Navigation blocking protects user experience; it does not persist data or replace server-side concurrency control.

File: `src/features/editor/Editor.tsx`

```tsx
import { useBlocker } from '@tanstack/react-router'

function LeaveGuard({ isDirty }: { isDirty: boolean }) {
  const blocker = useBlocker({
    shouldBlockFn: () => isDirty,
    enableBeforeUnload: isDirty,
    withResolver: true,
  })

  if (blocker.status !== 'blocked') return null

  return <div role="alertdialog" aria-modal="true" aria-labelledby="leave-title">
    <h2 id="leave-title">Discard unsaved changes?</h2>
    <button type="button" onClick={blocker.proceed}>Leave</button>
    <button type="button" onClick={blocker.reset}>Stay</button>
  </div>
}
```

## Practice and verification

### Completion checkpoint

Client navigation and page unload are blocked only while the form is dirty and unblock immediately after save.

### Exercise

Implement leave, stay, and save-then-leave flows and write an interaction test for each.

### Verification

Test Link, back, refresh, and save behavior; confirmation should appear only for unsaved state.

### Common pitfalls

- Prompting for every navigation even when the form is unchanged.
- Blocking Router navigation while missing browser close or refresh.

## Official sources

- https://tanstack.com/router/latest/docs/guide/navigation-blocking
