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

React Router V6下阻止未保存修改时应用内页面导航的方案

React Router v6 应用内未保存修改导航拦截方案

针对React Router v6移除Prompt/usePrompt后的导航拦截需求,以下是两种可行方案,结合你的isDirty状态实现完整的拦截逻辑:

方案一:使用useNavigation的block方法(推荐)

该方法能拦截所有应用内导航动作(包括Link点击、浏览器前进后退、navigate调用),同时搭配useBeforeUnload处理页面刷新/外部跳转:

import { useNavigation, useBeforeUnload, useCallback } from 'react-router-dom';
import { useEffect, useState } from 'react';

function YourEditComponent() {
  const [isDirty, setIsDirty] = useState(false);
  const navigation = useNavigation();

  // 拦截应用内导航
  useEffect(() => {
    const unblock = navigation.block((tx) => {
      if (!isDirty) {
        tx.retry();
        return;
      }

      const confirmLeave = window.confirm('你有未保存的修改,确定要离开吗?');
      if (confirmLeave) {
        tx.retry();
      } else {
        tx.abort();
      }
    });

    return unblock;
  }, [navigation, isDirty]);

  // 处理页面刷新/外部跳转
  useBeforeUnload(
    useCallback((e) => {
      if (isDirty) {
        e.preventDefault();
        (e as BeforeUnloadEvent).returnValue = '';
      }
    }, [isDirty])
  );

  // 其他组件逻辑...
  return (
    // 你的表单内容...
  );
}

关键说明:

  • navigation.block接收的回调中,tx是导航事务对象:
    • tx.retry():允许继续执行导航
    • tx.abort():终止当前导航
  • 组件卸载时必须调用unblock清理拦截,避免内存泄漏

方案二:自定义拦截式链接组件(补充方案)

如果只需要拦截通过Link触发的导航,可以自定义一个ConfirmLink组件替代原生Link:

import { Link, useNavigate } from 'react-router-dom';
import type { LinkProps } from 'react-router-dom';

type ConfirmLinkProps = LinkProps & {
  isDirty: boolean;
  confirmMessage?: string;
};

function ConfirmLink({ isDirty, confirmMessage = '你有未保存的修改,确定要离开吗?', ...props }: ConfirmLinkProps) {
  const navigate = useNavigate();

  const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
    if (isDirty) {
      e.preventDefault();
      const confirmLeave = window.confirm(confirmMessage);
      if (confirmLeave) {
        navigate(props.to as string);
      }
    }
  };

  return <Link {...props} onClick={handleClick} />;
}

// 使用方式
<ConfirmLink to="/other-page" isDirty={isDirty}>跳转到其他页面</ConfirmLink>

注意:

  • 该方案仅能拦截ConfirmLink的点击事件,无法处理浏览器前进后退、直接调用navigate的情况,需搭配方案一使用才能覆盖所有场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:12:48