Nextjs 페이지 나가기 확인창 띄우기

Wonwon·2023년 4월 10일
0

Nextjs

목록 보기
1/1

먼저 예시코드부터 보자.

// useOnBeforeUnload.ts
export const useOnBeforeUnload = () => {
const router = useRouter();
const [formChanged, setFormChanged] = useState<boolean>(false);

useEffect(() => {
  const warningText =
	  '저장되지않은 내용이 있습니다. 계속 진행하시겠습니까?';
  
  const handleWindowClose = (e: BeforeUnloadEvent) => {
	  if (!unsavedChanges) return;
	  e.preventDefault();
	  return (e.returnValue = warningText);
  };
  const handleBrowseAway = () => {
	  if (!unsavedChanges) return;
	  if (window.confirm(warningText)) return;
	  router.events.emit('routeChangeError');
	
	  if (router.asPath !== window.location.pathname) {
		  window.history.pushState('', '', router.asPath);
	  }
	  throw '페이지 이동이 취소되었습니다.';
  };
  
  window.addEventListener('beforeunload', handleWindowClose);
  router.events.on('routeChangeStart', handleBrowseAway);
  
  return () => {
	  window.removeEventListener('before unload', handleWindowClose);
	  router.events.off('routeChangeStart', handleBrowseAway);
  };
}, [formChanged]);
  
  return {formChanged, setFormChanged}
}

처음 필자 생각에는 아래사람의 예시와 같이 window.history.pushState('', '', router.asPath) 부분이 없어도 정상작동할줄 알았다.

const handleBrowseAway = () => {
	  if (!unsavedChanges) return;
	  if (window.confirm(warningText)) return;
	  router.events.emit('routeChangeError');
	
	  throw '페이지 이동이 취소되었습니다.';
  };
  

문제는 위의 코드는 nextjs의 component route는 막지만, path의 이동은 막지못하여 후처리를 해줘야했다.

const handleBrowseAway = () => {
	  if (!unsavedChanges) return;
	  if (window.confirm(warningText)) return;
	  router.events.emit('routeChangeError');
	
	  if (router.asPath !== window.location.pathname) {
		  window.history.pushState('', '', router.asPath);
	  }
	  throw '페이지 이동이 취소되었습니다.';
  };

아래와 같이 window, router에 모두 event를 등록하는것은 routeChangeStart은 route이동. 즉, 뒤로가거나 다른페이지로의 이동은 핸들링가능하나, 페이지 새로고침같은 이벤트는 핸들링 안되기 때문.

window.addEventListener('beforeunload', handleWindowClose);
  router.events.on('routeChangeStart', handleBrowseAway);
  

참고 링크 :
https://nextjs.org/docs/api-reference/next/router
https://github.com/vercel/next.js/issues/2694

profile
꾸준히 기록, 학습하려 노력하고 있습니다.

1개의 댓글

comment-user-thumbnail
2024년 1월 5일

React만 이용하고서는 동일한 기능을 구현할수 없을까요?
nextjs를 사용하고 있지 않는데 구현이 쉽지 않네요 ㅠ

답글 달기