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

如何在React-Router中监听页面刷新与窗口关闭并复用Prompt组件?

实现React-Router Prompt在刷新/关闭窗口时触发提示

首先得明确:React-Router的<Prompt>组件只负责拦截路由跳转(比如点击链接、调用history.push/replace),而页面刷新、窗口关闭属于浏览器层面的操作,需要单独通过beforeunload事件来处理。我们可以把这两个逻辑结合起来,保持提示的一致性。

核心思路

  • 用一个状态(比如isDirty)来标记是否需要触发提示(比如表单未保存时设为true)
  • 给<Prompt>组件设置when={isDirty},处理路由跳转时的拦截
  • 通过useEffect监听浏览器的beforeunload事件,在isDirty为true时触发关闭/刷新提示

完整代码示例

import { useState, useEffect } from 'react';
import { Prompt } from 'react-router-dom';

function YourComponent() {
  // 标记是否需要提示(比如表单未保存)
  const [isDirty, setIsDirty] = useState(false);
  const promptMessage = "你有未保存的更改,确定要离开吗?";

  // 处理页面刷新/关闭的提示
  useEffect(() => {
    const handleBeforeUnload = (event) => {
      if (isDirty) {
        // 大部分浏览器会忽略自定义消息,显示默认提示,但必须设置returnValue才能触发提示
        event.preventDefault();
        event.returnValue = promptMessage;
        return promptMessage;
      }
    };

    window.addEventListener('beforeunload', handleBeforeUnload);

    // 组件卸载时移除监听,避免内存泄漏
    return () => {
      window.removeEventListener('beforeunload', handleBeforeUnload);
    };
  }, [isDirty, promptMessage]);

  return (
    <>
      {/* React-Router的路由跳转拦截 */}
      <Prompt
        when={isDirty}
        message={promptMessage}
      />

      {/* 你的组件内容,比如表单 */}
      <input
        type="text"
        onChange={() => setIsDirty(true)}
        placeholder="输入内容..."
      />
      <button onClick={() => setIsDirty(false)}>保存</button>
    </>
  );
}

export default YourComponent;

注意事项

  • 浏览器自定义提示:现代浏览器(如Chrome、Firefox)会忽略你设置的promptMessage,显示浏览器自带的提示文本,但我们仍然需要设置event.returnValue并返回消息,才能触发提示弹窗。
  • 状态同步:确保isDirty状态能准确反映是否需要拦截(比如表单输入时设为true,保存后设为false)。
  • 清理监听:一定要在useEffect的返回函数中移除beforeunload事件监听,防止组件卸载后仍然触发,造成内存泄漏。

这样就能同时实现路由跳转拦截和页面刷新/关闭时的提示啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:15:04