우주먼지 개발 log
[TIL] 23/12/04 React 심화: 개인과제 이슈 모음(인증서비스가 들어간 팬레터함, 새로고침 이슈 등) 본문
[TIL] 23/12/04 React 심화: 개인과제 이슈 모음(인증서비스가 들어간 팬레터함, 새로고침 이슈 등)
개발자먼지 2023. 12. 4. 23:37강의를 다시 들으면서
하나하나 구현하니 오래 걸리긴하지만.. 하나도 기억이 안났는 걸..?
그래도 조금 많이 이해 완료
큰 이슈는 새로고침 이슈 빼고 모두 구현 완료! 👏
(TIL 쓸 때도 css 연습..ㅋ)
TIL 💡
Big Issue 1) 새로고침 이슈
requirement :
1) 로그인 상태인 경우 홈, 상세, 프로필 화면에만 접근,
로그아웃 상태에서는 로그인 화면에만 접근 할 수 있게 하기.
2) 새로고침시에도 로그인 상태가 유지되도록 로컬스토리지를 이용.
solution for 1) :
로그인을 알 수 있는 state 값에 따라
(예를 들어 isLogin, 혹은 accessToken이 있는지 없는지, 처음에는 전자로 구현했다가 후자로 바꿈)
라우터들을 분기 처리하고
다른 주소가 들어올 때는
로그아웃 상태에서는 "/login"으로,
로그인 상태에서는 "/" (홈)으로 리다이렉팅 하기.
예시 페이지와 동일하게 너무 잘했다. 1) 번은..
그런데 말입니다..
여기서 몇시간 허공에 뿌린 새로고침 딜레마는 뭐냐면,
Issue:
1) redux 전역 state로 분기를 해주면 새로고침 하면 state값이 날아가면서 로그인 상태를 확인 할 수 없게 되어 로그인 화면으로 튕기게 된다.
2) 이를 해결 해 주기 위해 local storage를 반영하라고 했는데.. local storage에 값이 있는지 없는지로 router 분기를 하게 되면 로그인, 로그아웃 등 로그인 상태의 변경사항 발생 시 바로바로 화면에 반영이 안되기 때문에 오히려 새로고침을 해주어야 한다.
Try 1:
local storage에 써준 값을 다시 redux로 채워주는데
useEffect가 발동하기 전까지는 state가 비어있긴하다. 즉 페이지가 왔다갔다 해버림.
어느 타이밍에 채워줘야하느냐? ^.^
(위치도 애매해서 login 에서만 저걸 해주는 중, 로그인 후 화면들은 새로고침 시 문제 있겠네)
useEffect(() => {
const localUser = localStorage.getItem("user");
if (localUser)
dispatch(setLogin(JSON.parse(localUser)));
}, []);
Try 2:
비어있을 때에도 local storage 값을 유지 하도록 reudux initial 값에 local storage의 값을 써준다.
잘되는 줄 알았는데 로그인화면에서 local에 값 없을 때 에러뜨고 못고쳐서 망함.
해설 강의를 보자~~~
solution for 2) :
결국엔 try2 가 방향성은 맞긴 한데, 강의를 보고 확신을 갖고 보니 해결 할 수 있었다.
나의 문제는 현재 accessToken이 있는지 없는지로 로그인 여부를 판단하는것에서 시작한다.
복잡해서 포기해버린 것이나 다름 없다.
1) 처음에는 단순하게 isLogin : true 처럼 boolean 값으로 했었는데,
다른 동료분들과 얘기하다 보니 서버에서 받아온 값을 넣어주는 코드를 깔끔하게 두고 싶어서,
user 객체를 한번에 가져와서 redux와 local storage 에 저장을 해준 것이다.
여기local storage는 객체로 저장할 경우 넣고 빼는게 복잡해진다.
그래서 redux에서 써야하는 코드가 불편해졌다.
// 넣을 때
localStorage.setItem("user", JSON.stringify(userData));
// 뺄 때
const localUser = JSON.parse(localStorage.getItem("user"));
//그래서 redux의 initialState 에서는 이렇게 해줘야했고..
const initialState = {
accessToken: localUser?.accessToken,
}
2) Router에서 accessToken이 local storage에 없을 때 뭐가 나오는지 몰랐다. undefined...
//라우터 컴포넌트 내부 (전체구조 생략하였음)
const accessToken = useSelector((state) => state.auth.accessToken);
//return문 안쪽
{
accessToken != undefined ?
<Route path="/" element={Home/}>
:
<Route path="login" element={<Login />
}
강의 그대로 깔끔하게 수정하고자 하면
1) 로그인 시 userdata 객체로부터 뜯어서 토큰을 넣어주고
localStorage.setItem(" accessToken ", userdata.accessToken)
2) 리덕스 initialState에서는 isLogin을 여전히 true, false로 받는다.
const initialState = {
isLogin: !!localStorage.getItem("accessToken") // 느낌표두개로 boolean 타입으로 변경된다 핳...
}
3) Router에서 isLogin을 이용하여 삼항연산자를 깔끔하게 써준다.
isLogin ? <Route> : <Route>
- 끝-
Big Issue 2) accessToken 만료 시 로그아웃 시키기
여기서 또 몇시간 공중에 흩뿌린 문제가 나오는데...
interceptor로 accessToken 확인하는 통신을 추가했는데,
이 안에서는 dispatch안되지, navigate 안되지,
모든 react hook을 사용 할 수 없다는 에러가 뜬다는 것이다~ 랄라.
임시 방편으로 localStorage는 접근이 가능해서 로컬 스토리지의 accessToken과 user 정보를 지우고, window.location.replace('/login');
을 사용했지만 이유를 몰라서 세상 찝찝하다.
(강의는 아직 다 못봄)
Small Issues
1) 귀신이 곡할 코드 👻
configStore.js 에 reducer 추가 안해주면 에러는 안나지만 계속 state값 못 받아와서 undefined,
귀신이 곡할 코드가 완성된다. 괜히 동기 분 괴롭힘^^;
2) 똥코드 💩 🤎
reducer 에서 mutable한 함수를 써줘도 불변성을 유지하게 해준다는 immer js만 믿고
state가 객체일 때
state.content = action.payload; 이런게 가능하길래
객체 자체를 통째로 변경하고자
state = action.payload; return state; 라고 써줬다가 망한 썰 (이걸 해준다고 한게 아닌데..)
action.payload는 여기서 reducer를 벗어나면 없어지고
state는 action.payload를 가리키고 있어서 null이 나오는 것 같다. 나이스^.^
'TIL(Today I Learned) > 스파르타 내배캠' 카테고리의 다른 글
[TIL] 23/12/06 React 심화: 아웃소싱 프로젝트 (React Query 마스터하기) (0) | 2023.12.06 |
---|---|
[TIL] 23/12/05 React 심화: 아웃소싱 프로젝트 (데이트 코스 페이지) 개요 (0) | 2023.12.06 |
[TIL] 23/12/01 React 심화: 개인과제 (인증서비스가 들어간 팬레터함) (0) | 2023.12.04 |
[TIL] 23/12/01 React 심화: 조건부스타일링 연습 (feat. styled-components) (0) | 2023.12.01 |
[TIL] 23/11/29 React 심화: Redux를 Redux Toolkit 으로 리팩토링 (0) | 2023.11.30 |