UnsavedAlertDialog.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import React, { useCallback, useEffect, memo } from 'react';
  2. import { useTranslation } from 'next-i18next';
  3. import { useRouter } from 'next/router';
  4. import { useIsEnabledUnsavedWarning } from '~/stores/editor';
  5. const UnsavedAlertDialog = (): JSX.Element => {
  6. const { t } = useTranslation();
  7. const router = useRouter();
  8. const { data: isEnabledUnsavedWarning, mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
  9. const alertUnsavedWarningByBrowser = useCallback((e) => {
  10. if (isEnabledUnsavedWarning) {
  11. e.preventDefault();
  12. // returnValue should be set to show alert dialog
  13. // default alert message cannot be changed.
  14. // See -> https://developer.mozilla.org/ja/docs/Web/API/Window/beforeunload_event
  15. e.returnValue = '';
  16. return;
  17. }
  18. }, [isEnabledUnsavedWarning]);
  19. const alertUnsavedWarningByNextRouter = useCallback(() => {
  20. if (isEnabledUnsavedWarning) {
  21. // eslint-disable-next-line no-alert
  22. window.alert(t('page_edit.changes_not_saved'));
  23. mutateIsEnabledUnsavedWarning(false);
  24. }
  25. return;
  26. }, [isEnabledUnsavedWarning, mutateIsEnabledUnsavedWarning, t]);
  27. /*
  28. * Route changes by Browser
  29. * Example: window.location.href, F5
  30. */
  31. useEffect(() => {
  32. window.addEventListener('beforeunload', alertUnsavedWarningByBrowser);
  33. return () => {
  34. window.removeEventListener('beforeunload', alertUnsavedWarningByBrowser);
  35. };
  36. }, [alertUnsavedWarningByBrowser]);
  37. /*
  38. * Route changes by Next Router
  39. * https://nextjs.org/docs/api-reference/next/router
  40. */
  41. useEffect(() => {
  42. router.events.on('routeChangeStart', alertUnsavedWarningByNextRouter);
  43. return () => {
  44. router.events.off('routeChangeStart', alertUnsavedWarningByNextRouter);
  45. };
  46. }, [alertUnsavedWarningByNextRouter, router.events]);
  47. return <></>;
  48. };
  49. export default memo(UnsavedAlertDialog);