如何在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
相关产品推荐
相关产品推荐

