48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
![]() |
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||
|
import { t } from '@lingui/macro';
|
||
|
import { Modal } from 'antd';
|
||
|
import { ANT_PREFIX_CLASS } from 'consts';
|
||
|
import React, { useEffect, useRef, useState } from 'react';
|
||
|
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||
|
|
||
|
function FormBlocker({ block }) {
|
||
|
const [isBlocking, setIsBlocking] = useState(false);
|
||
|
const [hasShownModal, setHasShownModal] = useState(false); // prevent multiple modals from showing
|
||
|
const nextLocationRef = useRef(null);
|
||
|
|
||
|
useBlocker((transition) => {
|
||
|
if (block) {
|
||
|
setIsBlocking(true);
|
||
|
nextLocationRef.current = transition.nextLocation;
|
||
|
setHasShownModal(false);
|
||
|
|
||
|
return !isBlocking;
|
||
|
}
|
||
|
return false;
|
||
|
});
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (isBlocking && !hasShownModal) {
|
||
|
setHasShownModal(true);
|
||
|
Modal.confirm({
|
||
|
title: t`You have unsaved changes!`,
|
||
|
content: t`Are you sure you want to leave without saving?`,
|
||
|
icon: <ExclamationCircleOutlined />,
|
||
|
closable: true,
|
||
|
prefixCls: ANT_PREFIX_CLASS,
|
||
|
onOk() {
|
||
|
setIsBlocking(true);
|
||
|
window.location.href = nextLocationRef.current.pathname;
|
||
|
},
|
||
|
onCancel() {
|
||
|
setIsBlocking(false);
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
}, [isBlocking, nextLocationRef, hasShownModal]);
|
||
|
|
||
|
return <div key={block as unknown as React.Key}></div>;
|
||
|
}
|
||
|
|
||
|
export default FormBlocker;
|