- signin 페이지에서 토큰값을 인식해 todo 페이지로 넘어가는 로직에서 Context API 에 들어있는 토큰 값 반영이 null 로 되어있다. 어플리케이션에는 값이 담겨있지만, App.tsx 에서 console.log(acces_token) 으로 출력해보니 null 로 나왔다.
- 페이지 이동(signin -> todo 페이지) 할 때 token 이 null 에서 상태 변경이 되지 않는 문제였다.
- 하지만 새로 고침을 하면 다시 토큰값이 불러와져서 정상적으로 Todo 페이지가 보여진다.
<결론>
- Signin 페이지에서 Todo 페이지로 이동할 때 토큰이 불러와지지 않고(null 상태), 새로 고침을 해야지만이 토큰값이 불러와진다. 즉, null 상태에서 token 값으로 상태 변경이 되지 않는 다는 것
🤔궁금증1) 왜 null 상태에서 token 값으로 상태 변경이 되지 않을까? - App.tsx 에서 localStorage에서 access_token을 불러와 UserContext를 설정하는 과정과, Router 컴포넌트가 처음 렌더링될 때 useContext(UserContext)를 사용해 token을 불러오는 과정 사이에 동기화 문제가 있을 수 있다. - App 컴포넌트가 처음 렌더링 되면 localStorage 에서 access_token 을 불러와 UserContext.Provider의 value로 설정한다. 그러나 이 시점에서는 아직 localStorage 에 access_token 이 저장되지 않았을 수 있다. 따라서 UserContext.Provider의 value 는 null 이 된다. - 그 후 , 사용자가 로그인에 성공하면 localStorage 에 access_token 이 저장되지만, UserContext.Provider의 value가 변경되지 않으므로 Router 컴포넌트가 useContext(UserContext)를 사용해 token을 불러올 때 null을 반환한다.
🤔궁금증2) localStorage.getItem 메서드를 통해 토큰이 있으면 가져오는 건데, access_token 변수가 로그인이 성공하면 null 에서 토큰값으로 왜 자동으로 변경이 안되는거지? 새로고침을 해야만 토큰값이 업데이트가 되지? Context API 는 상태 변경 감지가 안되는건가?
- Context API 는 변경을 감지하는 기능이 포함되어있다. Context.Provider 의 'value' prop 이 변경되면 해당 컨텍스트를 구독하고 있는 모든 컴포넌트들은 다시 렌더링된다. 이 때, 'useContext' Hook 을 사용하는 컴포넌트 들은 새로운 컨텍스트 값을 받아와서 사용하게 된다. 하지만, Context API 는 React 컴포넌트의 렌더링 생명주기에 따라 컨텍스트의 값이 업데이트 되고 반영된다. 상태(state) 변경을 감지하여 컴포넌트를 다시 렌더링 하는 방식으로 작동한다. 상태는 특별한 React 기능인 'useState'나 'useReducer'같은 Hook을 사용해 관리한다. 이런 Hook 을 사용해서 상태를 업데이트 할 때만 React는 변경을 감지하고 컴포넌트를 다시 렌더링한다.
즉, 'localStorage'에 값을 설정한 후에 바로 'useContext'로 그 값을 가져올 수 없다는 것이다. 왜냐하면 'localStorage'의 값이 변경되더라도 state가 변경된 것이 아니기 때문에 React가 인지할 수 없기 때문이다. localStorage가 React의 생명주기와 상태 관리 체계와는 별개로 동작하기 때문이다.
예를 들어, 아래와 같은 코드가 있다.
localStorage.setItem을 호출하여 value를 'new value'로 변경했지만, value 변수는 여전히 'old value'를 가지고 있다. 이는 value 변수에 저장된 값은 변경되지 않았기 때문이다. JavaScript는 value 변수가 localStorage에 저장된 'value' 항목과 연결되어 있음을 자동으로 인지하지 않는다. 이와 마찬가지로, React 컴포넌트는 localStorage의 변화를 자동으로 감지하지 않는다. 이런 경우에는 상태 관리 메커니즘을 통해 localStorage의 변화를 수동으로 감지하고 반영해야 한다. 이 때 useState와 useEffect를 사용할 수 있습니다.
2. 해결책
1) 로그인에 성공할 때 UserContext.Provider의 value를 업데이트해야하지 않을까? 즉, 토큰값이 null 에서 실제 토큰값으로 상태 업데이트를 해주어야 하지 않을까?
- 상태 업데이트를 위해 UserContext 기본값에 useState로 관리하는 token 과 setToken 을 넣었다.