コチラでございます。
import { useEffect } from 'react';
/**
* 一度入力した後にリロードすると、確認ダイアログを出す。
*/
export const useOnReloadAlert = (enable: boolean = true) => {
useEffect(() => {
if (!enable) return;
window.history.pushState(null, '', window.location.pathname);
const onReload = (event: BeforeUnloadEvent) => {
event.preventDefault();
event.returnValue = '';
};
window.addEventListener('beforeunload', onReload);
return () => {
window.removeEventListener('beforeunload', onReload);
};
}, [enable]);
};
enable: boolean
オプションは、特定の条件化でブラウザバックアラートを出したくないので、追加しました。
具体的なケースは、SPA上で 入力 -> プレビュー -> 完了
の画面遷移を行う場合です。
ページ遷移してしまえばいいのですが、わざわざrecoilやcontextで構築するほどでもないな〜という気持ちで、state管理で進めた結果以下の構成となり、
type PageType = 'create' | 'preview' | 'complete';
...
const { values, ...handlers } = useXXXForm();
switch (pageType) {
case 'create':
return <CreatePage values={values} {...handlers} />;
case 'preview':
return (
<PreviewPage values={values} />
);
case 'complete':
return <CompletePage handleSubmit={handlers.handleSubmit} />;
}
で、この場合ですと、completeから離脱する際にもhooksが発火してしまう可能性があります。
(e.g. stripeの決済ページcheckoutなど)
そういうシーンで以下のようにオプションを渡す場合にお使いください!
const enableOnReloadAlertPages = new Set<UserPreviewPageType>(['create', 'preview'])
useOnReloadAlert(enableOnReloadAlertPages.has(pageType));
不要な場合は以下で大丈夫です!
import { useEffect } from 'react';
/**
* 一度入力した後にリロードすると、確認ダイアログを出す。
*/
export const useOnReloadAlert = () => {
useEffect(() => {
window.history.pushState(null, '', window.location.pathname);
const onReload = (event: BeforeUnloadEvent) => {
event.preventDefault();
event.returnValue = '';
};
window.addEventListener('beforeunload', onReload);
return () => {
window.removeEventListener('beforeunload', onReload);
};
}, []);
};