페이지 이동 방지 / 글 작성시 페이지 이동 방지, 경고
글 작성시 페이지 이동을 방지한다.
nextjs 에서 페이지 이동시 router 를 이용하여 이동함.
새로고침, router 이동, 뒤로가기를 방지하였다.
BeforeUnloadEvent 윈도우 변화 전 이벤트 이용.
routeChangeStart 라우터 변화 전 이벤트 이용.
뒤로가기 시 이벤트로 이동은 방지 되지만, router 변경이 아니라 url이 이동되는 url로 변경됨 -> history를 이용하여 변경 전 page로 link 변경
// form에 내용이 있을때 changeForm=true 변경
const [changeForm, setChangeForm] = useState(false);
// 페이지 이동 수락시 이동할 url 저장
const [toUrl, setToUrl] = useState("");
// 페이지 이동 수락 true/false
const [confirmed, setConfirmed] = useState(false);
// 페이지 이동 여부 check modal
const [openmmodal, setopenMmodal] = useState(false);
// 새로고침 방지
// changeForm = true -> 새로고침 방지 -> 페이지 이동확인 팝업.
const handleBeforeunload = (e: BeforeUnloadEvent) => {
if (changeForm) {
e.preventDefault();
e.returnValue = "";
return "";
}
return undefined;
};
// 라우터 이동 방지
const routeChangeStart = useCallback(
(url: string) => {
if (
router.asPath.split("?")[0] !== url.split("?")[0] &&
!confirmed &&
changeForm
) {
// 뒤로가기 시 page url 비교 후 글작성 url로 변경
if (router.asPath !== window.location.pathname) {
window.history.pushState("", "", router.asPath);
}
setToUrl(url);
//전역 모달 - confirnmodal
// 취소 -> toUrl 초기화, 모달 off
// 확인 -> 페이지 이동
showModal({
modalType: "ConfirmModal",
modalProps: {
title: "페이지를 이동하시겠습니까?",
text: "변경사항이 저장되지 않을 수 있습니다.",
leftbtnfunc: () => {
setToUrl("");
hideModal();
},
rightbtnfunc: () => setConfirmed(true),
},
});
//강제 router error 발생시켜 페이지 이동 방지
router.events.emit("routeChangeError");
throw "Abort route change. Please ignore this error.";
}
},
[confirmed, changeForm, router.asPath, router.events, openmmodal]
);
useEffect(() => {
//window 새로고침시 이벤트핸들러
window.addEventListener("beforeunload", handleBeforeunload);
// router 변화시 이벤트 헨들러
router.events.on("routeChangeStart", routeChangeStart);
return () => {
window.removeEventListener("beforeunload", handleBeforeunload);
router.events.off("routeChangeStart", routeChangeStart);
};
}, [routeChangeStart, router.events]);
useEffect(() => {
// 수락시 이동
if (confirmed) {
setopenMmodal(false);
router.replace(toUrl);
}
}, [toUrl, confirmed]);
const onSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
/... 생략 .../
// 글 작성 완료시 페이지 이동 수락 -> 이동.
setConfirmed(true);
router.push("/");
}
useEffect(() => {
// 수락시 이동
if (confirmed) {
hideModal();
// toUrl 상태에 따른 router 이동
if (toUrl !== "") {
router.replace(toUrl);
} else {
router.push("/");
}
}
}, [toUrl, confirmed]);
const onSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
/... 생략 .../
// 글 작성 완료시 페이지 이동 수락 -> 이동.
setConfirmed(true);
}