浏览文档目录
第 12 课 · 保护未保存输入

在离开脏表单前阻止导航

用 useBlocker 同时处理路由内导航与浏览器卸载,并为自定义确认界面建立明确状态。

TanStack Router进阶18 分钟REV 02Markdown .md
完成后你将能够

能只在表单有未保存修改时注册阻塞器,并正确连接继续、留下与关闭标签页行为。

01

阻塞条件应来自真实脏状态

shouldBlockFn 返回 true 表示阻止导航。enableBeforeUnload 负责刷新、关闭标签页等浏览器级卸载;应当只在 isDirty 为 true 时启用,避免用户离开干净页面也收到系统提示。

02

自定义确认需要 resolver

withResolver: true 时,status 变为 blocked 后再显示界面。proceed 允许本次导航,reset 保持当前页面。保存成功后先清除脏状态,避免后续导航再次被旧状态拦截。

src/features/editor/Editor.tsxtsx
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>
}
实践

把本课变成可验证的能力

完成检查点

只有表单为脏时才阻止客户端导航和页面卸载,保存成功后立即解除。

动手练习

实现继续离开、留在页面和保存后离开三条流程,并为每条流程编写交互测试。

验证方法

测试 Link、后退、刷新和保存四种行为;确认框只应在未保存状态出现。

常见错误
  • 所有导航都弹确认框,即使表单没有变化。
  • 只拦截 Router 导航而漏掉浏览器关闭或刷新。
SOURCE REFERENCES · CHECKED 2026-08-03https://tanstack.com/router/latest/docs/guide/navigation-blocking