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

React路由切换时如何实现自定义确认提示?

React Router 全局路由切换确认提示实现方案

原代码问题分析

  1. 原生Link组件的默认跳转行为不会被onClick中的逻辑阻止,即使用户取消确认,路由依然会跳转
  2. 每个Link都需要单独绑定处理函数,无法实现全局统一拦截

方案一:自定义全局确认跳转组件(推荐)

创建一个封装了确认逻辑的自定义ConfirmLink组件,项目中所有路由跳转都使用这个组件,实现全局统一控制:

import { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import LoadingBar from "react-top-loading-bar";

// 自定义确认跳转组件
const ConfirmLink = ({ to, children, ...props }) => {
  const navigate = useNavigate();

  const handleClick = (e) => {
    // 阻止Link的默认跳转行为
    e.preventDefault();
    // 弹出确认框
    const isConfirm = confirm("确定要切换路由吗?");
    if (isConfirm) {
      // 用户确认后手动导航
      navigate(to);
    }
  };

  return (
    <Link to={to} onClick={handleClick} {...props}>
      {children}
    </Link>
  );
};

// 使用示例
export default function Demo() {
  const [progress, setProgress] = useState(0);

  return (
    <>
      <LoadingBar
        color="blue"
        progress={progress}
        onLoaderFinished={() => setProgress(0)}
        waitingTime={800}
        loaderSpeed={100}
        height={4}
      />
      <ul
        style={{
          display: "flex",
          justifyContent: "space-around",
          listStyle: "none"
        }}
      >
        <li>
          <ConfirmLink
            to="/"
            onClick={() => setTimeout(() => setProgress(100), 500)}
          >
            Home
          </ConfirmLink>
        </li>
        <li>
          <ConfirmLink
            to="/about"
            onClick={() => setTimeout(() => setProgress(100), 500)}
          >
            About
          </ConfirmLink>
        </li>
      </ul>
    </>
  );
}

方案二:全局拦截所有路由跳转(包括编程式导航)

如果需要拦截所有路由跳转行为(包括通过navigate方法的编程式跳转),可以将以下逻辑放在全局路由组件(如App.js)中:

import { useState, useEffect } from "react";
import { Link, useLocation, useNavigate, useNavigation } from "react-router-dom";
import LoadingBar from "react-top-loading-bar";

export default function Demo() {
  const [progress, setProgress] = useState(0);
  const location = useLocation();
  const navigate = useNavigate();
  const navigation = useNavigation();
  // 记录上一次路由地址,用于取消导航时回退
  const [prevLocation, setPrevLocation] = useState(location);

  useEffect(() => {
    // 当导航状态变为"loading"时,说明正在跳转路由
    if (navigation.state === "loading" && location !== prevLocation) {
      const isConfirm = confirm("确定要切换路由吗?");
      if (!isConfirm) {
        // 用户取消,导航回上一次路由
        navigate(prevLocation);
      }
    }
    // 更新上一次路由地址
    setPrevLocation(location);
  }, [navigation.state, location, prevLocation, navigate]);

  return (
    <>
      <LoadingBar
        color="blue"
        progress={progress}
        onLoaderFinished={() => setProgress(0)}
        waitingTime={800}
        loaderSpeed={100}
        height={4}
      />
      <ul
        style={{
          display: "flex",
          justifyContent: "space-around",
          listStyle: "none"
        }}
      >
        <li>
          <Link
            to="/"
            onClick={() => setTimeout(() => setProgress(100), 500)}
          >
            Home
          </Link>
        </li>
        <li>
          <Link
            to="/about"
            onClick={() => setTimeout(() => setProgress(100), 500)}
          >
            About
          </Link>
        </li>
      </ul>
    </>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 06:53:16