You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-hook-form如何检测表单未保存变更并在返回时弹出提示

你需要的未保存变更判断标识其实已经在你解构的formState属性中了,就是isDirty字段:它的定义是表单当前值和初始化传入的defaultValues是否存在差异,刚好匹配你要的「是否有未提交修改」的判断需求。

不同场景的实现方案

场景1:自定义返回按钮的点击拦截

直接在返回按钮的点击回调中增加判断逻辑即可,示例代码如下:

const handleBack = () => {
  // 存在未保存修改时弹出提示
  if (isDirty) {
    const confirmLeave = window.confirm("表单存在未保存的变更,确定要离开吗?");
    // 用户选择不离开则终止逻辑
    if (!confirmLeave) return;
  }
  // 此处写原有的返回逻辑,例如路由回退、关闭弹窗等
  navigate(-1);
}

场景2:拦截浏览器后退、刷新、关闭标签页行为

如果需要拦截浏览器原生的页面退出行为,可以监听beforeunload事件,在组件挂载时注册监听,卸载时移除即可:

import { useEffect } from 'react';

// ...其他代码

useEffect(() => {
  const handleBeforeUnload = (e) => {
    if (isDirty) {
      e.preventDefault();
      // 部分浏览器需要设置returnValue才会弹出提示
      e.returnValue = "表单存在未保存的变更,确定要离开吗?";
      return e.returnValue;
    }
  };
  window.addEventListener('beforeunload', handleBeforeUnload);
  // 组件卸载时移除事件监听,避免内存泄漏
  return () => window.removeEventListener('beforeunload', handleBeforeUnload);
}, [isDirty]);

场景3:拦截单页应用前端路由跳转(以React Router v6为例)

如果是单页应用,还需要拦截路由库的内部跳转逻辑,可以用对应路由库提供的拦截钩子,React Router v6可以用useBlocker实现:

import { useBlocker } from 'react-router-dom';

// ...其他代码

// 当isDirty为true时拦截路由跳转,弹出提示
useBlocker(() => {
  if (isDirty) {
    return window.confirm("表单存在未保存的变更,确定要离开吗?");
  }
  return false;
});

注意事项

  • 表单提交成功后如果需要重置isDirty状态,调用reset()方法即可,会将表单状态重置为初始的defaultValues,isDirty会自动变为false
  • 如果提交后需要更新默认比对基准为最新的表单值,可以给reset传入新的默认值:reset(newFormValues),后续isDirty会以新传入的值作为比对标准

内容的提问来源于stack exchange,提问作者Majed Badawi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 01:39:02