文章目录
封装hook
js
import { useEffect, useRef } from 'react';
import { Prompt, useHistory, useLocation } from 'react-router-dom';
/**
* 窗口关闭前提醒用户
*
* 参考:https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent
*/
export default function useWindowBeforeUnload(getMessage: () => string | undefined) {
const location = useLocation();
const history = useHistory();
const ref = useRef({
pathname: location.pathname,
}).current;
useEffect(() => {
// 定义提示函数
const promptBeforeUnload = (event: BeforeUnloadEvent) => {
const message = getMessage();
console.log('message before unload', message);
if (!message) return;
// 设置提示信息
event.preventDefault();
event.returnValue = message;
return message;
};
// 监听 onbeforeunload 事件
window.addEventListener('beforeunload', promptBeforeUnload);
return () => window.removeEventListener('beforeunload', promptBeforeUnload);
});
// hash 路由下存在问题,需要谨慎使用
// 问题:跳转时如果取消了,路由依然会发生辩护,导致下次跳转相同路由,不会出现提示,且刷新页面会进入到目标页面
const renderPrompt = () => (
<Prompt
when={!!getMessage()}
message={(location, action) => {
const message = getMessage();
if (message) return `${message}(即将跳转:${location.pathname}${location.search})`;
return false;
}}
/>
);
return { renderPrompt };
}
使用hook
js
import useWindowBeforeUnload from '@/hooks/useWindowBeforeUnload';
export default function () {
const { renderPrompt } = useWindowBeforeUnload(() => {
return '如果有未保存的修改,离开后将会丢失!';
});
return (
<div>
{renderPrompt()}
</div>
);
}