[nextJs]페이지 이동 방지 / 글 작성시 페이지 이동 방지, 경고

최영진·2023년 2월 28일
0

NextJs

목록 보기
7/7

페이지 이동 방지 / 글 작성시 페이지 이동 방지, 경고

글 작성시 페이지 이동을 방지한다.
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("/");
     
    }
  • 수정 - 글작성 완료시 setConfirmed(true) 는 state가 마지막으로 적용되어 페이지이동방지 모달이 페이지 이동도중 보여짐.
    router.push('/') 를 confirm 이 의존배열인 useEffect에 넣어 해결함.
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);
     
    }
profile
안녕하시오.

0개의 댓글