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

React Router v7中能否用history.listen拦截页面beforeunload事件?

在React Router v7中实现离开页面前保存表单

问题背景

升级到React Router v7后,原通过自定义history实例监听导航并触发beforeunload的方式失效(v7不再支持传入自定义history),而useLocation配合useEffect只能在路由跳转后执行逻辑,无法在跳转前完成表单保存。

解决方案

结合React Router内置钩子与原生事件,同时处理路由跳转和浏览器关闭/刷新两种场景:

1. 封装自定义钩子统一处理

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

// 自定义钩子:离开页面(路由跳转/浏览器关闭)前保存表单
function useSaveFormOnLeave(saveFormHandler, isFormModified) {
  // 拦截路由跳转,跳转前保存表单
  useBlocker((navigation) => {
    if (isFormModified) {
      saveFormHandler(); // 执行表单保存逻辑
      navigation.proceed(); // 允许完成路由跳转
    }
  });

  // 监听浏览器关闭/刷新事件,触发保存
  useBeforeUnload((event) => {
    if (isFormModified) {
      saveFormHandler();
      // 触发浏览器默认提示(部分现代浏览器会忽略自定义文本)
      event.preventDefault();
      event.returnValue = '';
    }
  });
}

2. 在表单组件中使用

import { useState, useMemo } from 'react';

function EditForm() {
  const [formValues, setFormValues] = useState({ name: '', email: '' });
  // 假设初始表单值来自接口或props
  const initialFormValues = { name: '', email: '' };

  // 判断表单是否有未保存的修改
  const isFormDirty = useMemo(() => {
    return Object.keys(formValues).some(key => formValues[key] !== initialFormValues[key]);
  }, [formValues, initialFormValues]);

  // 表单保存逻辑(示例:可替换为API请求或本地存储)
  const saveForm = () => {
    console.log('保存表单数据:', formValues);
    // 这里可以添加实际保存逻辑,比如:
    // await api.saveForm(formValues);
  };

  // 使用自定义钩子
  useSaveFormOnLeave(saveForm, isFormDirty);

  // 表单渲染
  return (
    <form>
      <input
        type="text"
        value={formValues.name}
        onChange={(e) => setFormValues(prev => ({ ...prev, name: e.target.value }))}
        placeholder="姓名"
      />
      <input
        type="email"
        value={formValues.email}
        onChange={(e) => setFormValues(prev => ({ ...prev, email: e.target.value }))}
        placeholder="邮箱"
      />
    </form>
  );
}

关键说明

  • useBlocker:React Router v6.4+(含v7)提供的导航拦截钩子,能在路由跳转前触发回调,确保保存逻辑先执行。
  • useBeforeUnload:专门处理浏览器关闭、刷新场景的钩子,与原生beforeunload事件对应。
  • isFormDirty:通过对比表单当前值与初始值,避免无意义的重复保存,优化性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:01:13