새창에서 부모창 상태 변경 (window.opener로 함수 실행하기)
구현 목표
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초후 창 닫기, 연결 외에 리스트를 조회해야하는 경우 리스트 페이지로 이동하기 등등..