TIL

새창에서 변경한 상태값을 기존창에서도 변경시키는 방법(window.opener로 함수 실행하기)

빔네모 2023. 11. 26. 01:11

 

구현 목표

1. 계정 설정 페이지에서 연동하기 버튼 클릭시 새창을 열어 소셜 로그인을 진행

2. 외부 사이트가 열리고 소셜 로그인에 성공하면 열린 새창에서 기존 도메인 주소로 리다이렉트

3. window.close()를 이용하여 창 닫음

4. 창이 닫히면서 기존에 '연동하기' 버튼이 '연동해제' 버튼으로 바뀌어야함

 


문제 상황

  • 연동하기 버튼은 계정 연동이 완료된 후에 연동해제 버튼으로 값이 바뀌어야함. 이 바뀐다는 기준은 state값으로 관리함. 그래서 리다이렉트된 주소에서 리코일을 이용해 state 값을 바꿔줌 (둘은 부모 자식 관계가 아니기에 props로 해결할 수 없음)
  • 연동해제일 경우에는, 기존 창에서 해제만 하기 때문에 상태값이 잘 바꿔짐. 하지만 연동하기 버튼은 새창을 열어서 상태값을 바꾸기 때문에 새창에서 바뀐 상태값이 기존 창의 상태값에 영향을 주지 못함
 
현 사이트를 플로우를 도식화

로그인 후 페이지 이동이 일어나는 기존 소셜로그인과 달리 리다이렉트 창 / 기존창을 별개로 봐야된다.

기존창은 사용자가 새창에서 진행한 활동을 모두 끝낸후에 변경된다....

 


선택지

​1. 새창을 열지 않고 연동하기

=> 상태를 변경할 수 있으나, 구현 조건에는 맞지 않음

2. 연동 성공 후 새로고침 하기

=> 새로고침하면 새로운 상태로 업데이트 되므로 상태값은 변하지만 화면을 다시 그려야 함으로 성능적으로 좋지 않음

3. window.opener.postMessage

=> 이벤트를 전달하고 수신하기. 일단 구현 실패, 그리고 해당 이벤트를 수신할때까지 함수가 계속 실행됨

4.window.opener로 함수 실행하기

 

// 기존 창
  //윈도우 객체에 함수 추가
  /**소셜로그인 연동 여부 */
  window.updateParentState = () => {
    setLinkConnect(true);
  };

 

소셜로그인 연동시 상태값을 바꿔주는 함수를 윈도우 객체에 추가한다.

  /**소셜로그인 연동 버튼 */
  const onHandleConnect = () => {
    if (isConnect) {
      deleteConnect()
        .then((res) => {
          setLinkConnect(false);
          Notiflix.Notify.success(t(IK.clear));
        })
        .catch((res) => Notiflix.Report.failure(t(IK.again_message), t(IK.again_message), t(IK.comfirm)));
    } else {
      const link = process.env.REACT_APP_MEDIT;
      setIsOnlyLinkConnect(true);
      window.open(`${link }`, "_blank", "width=560,height=560");
    }
  };

 

연결되어 있는 경우에는 연결 해제 api 호출 후 성공하면 상태 변경

연결되어있지 않는 경우에는 새창을 열어 소셜 로그인을 진행한다.

 

//리다이렉트 컴포넌트

  useEffect(() => {
    postLinkCode(code)
      .then((res) => {
        if (isOnlyConnection) {
          window.opener.updateParentState(); // 부모 창의 함수 호출하여 상태 변경
          Notiflix.Notify.success(t(IK.medit_success));
          setTimeout(() => {
            window.close();
          }, 3000);
        } else {
          nav("/list");
        }
      })
      .catch((res) => {
        //에러처리
      });
  }, []);

 

소셜로그인에 성공하면 현 사이트 주소로 리다이렉트 된다.

사이트 화면이 마운트 될 시점에 useEffect를 이용해 부모 창의 함수를 호출하여 상태를 변경한다.

나머지 코드는 성공한 경우 3초후 창 닫기, 연결 외에 리스트를 조회해야하는 경우 리스트 페이지로 이동하기 등등..