닉네임을 입력받는 모달창에서 다시 뒤로 돌아가서 로그인 정보를 바꾸고 싶거나
게스트 모드로 진행을 희망할 경우를 대비해서 뒤로가기 기능을 추가해야 했다
처음에는 단순히 AskNickNameModal 창에서 뒤로가기 버튼만 추가하고
useNavigate로 뒤로 이전 페이지로 돌아가면 될 줄 알았지만...
const onClose = () => {
// 뒤로가기 로직
closeModal(); // 모달 창 닫기
};
return (
<div>
피파온라인 계정과 연동을 위해 피파온라인에서 사용하고 계시는 닉네임을 입력 해 주세요!
<form onSubmit={closeModalAndGotoHome}>
<input onChange={onChange} value={nickNameInput} />
<input type="submit" value="확인" />
</form>
{/* 버튼 추가 */}
<button type="button" onClick={onClose}>
뒤로가기
</button>
</div>
);
당연히 제대로 동작하지 않았다
여기서 AskNickNameModal 이 뜨는 시점에 대해 고민을 할 필요가 있다
해당 모달은 로그인을 하고 나서 DB에 피파온라인 계정 정보가 없을 시 발생된다
즉, 로그인이 이미 되었다는 것이다
그렇다면 모달창이 떴을 땐 이미 로그인이 되어 있다는 것을 의미하며 단순한 뒤로가기가 아닌 ,
로그아웃 또한 동시에 진행해야 했다
전역 context로 사용하던 로그인 관련 context를 불러와서 로그아웃을 처리를 한다
const { setIsLoggedIn } = useLoginAPI()!;
...
const onClose = () => {
signOut(authService);
closeModal();
};
그렇지만 useLoginAPI 값을 계속 불러올 수 없다는 에러가 발생했다
알고보니 당시 context를 사용하기 위해 Provider로 감싸는 구조가 아래와 같았는데
자세히 보면 ModalProvider가 LoginProvider보다 상위에 있다
즉 , 모달창에서 로그인context를 사용할 수 없는 구조였던 것이다
왜냐하면 현재 모달창 또한 전역 context레벨에서 사용중이기 때문이다
( Outlet이 아닌 , ModalProvider 가 선언된 위치에 있다는 소리 )
import React, { useEffect, useState } from 'react';
import { Outlet } from 'react-router-dom';
import { LoginProvider } from './Context/Firebase/LoginContext';
import { ModalProvider } from './Context/Modal/ModalContext';
import { UserObjProvider } from './Context/UserObj/UserObjContext';
function App() {
return (
<UserObjProvider>
<ModalProvider>
<LoginProvider> // ModalProvider 하위에 LoginProvider 존재
<Outlet />
</LoginProvider>
</ModalProvider>
</UserObjProvider>
);
}
export default App;
그러므로 LoginProvider가 보다 상위에 있도록 이 둘의 위치를 바꿔서 이 문제를 해결한다
import React, { useEffect, useState } from 'react';
import { Outlet } from 'react-router-dom';
import { LoginProvider } from './Context/Firebase/LoginContext';
import { ModalProvider } from './Context/Modal/ModalContext';
import { UserObjProvider } from './Context/UserObj/UserObjContext';
function App() {
return (
<UserObjProvider>
<LoginProvider> // LoginProvider가 ModalProvider 상위에 존재
<ModalProvider>
<Outlet />
</ModalProvider>
</LoginProvider>
</UserObjProvider>
);
}
export default App;
각 context가 중첩된 순서에 따라 해당 context를 사용할 수 있는 범위가 달라진다는 것에 대해 깨닫게 되었다
그렇지만 또 다른 문제가 발견됐다
모달창이 생성되지 않고 다음 단계로 넘어가버림
>> 문제이렇게 닉네임을 입력받는 모달창에서 뒤로가기를 한번 선택하고 , 다시 로그인을 선택 하게 되면
동일하게 DB에 계정 정보가 없으므로 다시 모달창이 띄워져야 하는데
바로 넘어가는 문제가 발생했다
해당 문제는 알고 보니 DB에 기존 계정 정보가 존재하는지에 대해 알려주는
isNickNameExist 플래그 상태값의 문제였다
기존에 모달창은 아래와 같은 isNickNameExist의 상태값을 기반으로 띄워주고 있었다
useEffect(() => {
isNickNameExist ? '' : openModal(<AskNickNameModal />);
}, [isNickNameExist]);렇
그렇지만 자세히 생각해보면 , 모달창에서 뒤로 가기 선택을 했을 때
이 과정에서 로그아웃을 하게 되면 로그아웃은 진행하지만
isNickNameExist 상태값은 그대로 유지가 된다
즉, useEffect의 의존성 배열이 변하지 않아 재로그인 시 , 모달창이 띄워지는
useEffect 로직 자체가 생략되는 것이었다
모달창이 띄워진 것이면 isNickNameExist 가 false
뒤로가기를 진행하면 그대로 isNickNameExist 가 false로 유지
다시 로그인 하게 되면 isNickNameExist 가 false이지만 , 문제는 isNickNameExist 가 바뀐 것이 아니므로 useEffect 로직 자체가 생략
그러므로 로그아웃이 됐을 때 의도적으로 isNickNameExist 를 true로 바꿔줘서 문제를 해결했다
다시 로그인 시 , false가 된다면 그때 (true→false이므로)useEffect가 실행되는 것이다
(어차피 false일때만 useEffect가 제대로 실행되면 됨)
if (!user) {
console.log('logged out');
setIsNickNameExist(true); // 모달 창에서 뒤로가기 선택시
// useEffect를 실행하기 위해 의도적으로 isNickNameExist를 초기값으로 세팅
setIsLoggedIn(false);
setUserObj(null);
}