본문 바로가기
Web Development/React

React / 토큰 유무에 따른 조건부 랜더링 / token undefined가 true로 인식되는 오류 해결

by Krystal K 2023. 5. 17.

토큰 유무에 따른 조건부 랜더링 

token undefined가 true로 인식되는 오류 해결 


구현하려는 기능 

토큰 유무에 따라 조건부 랜더링으로 다른 결과값 출력

 

 

내가 생각한 로직

1. 로그인 버튼을 누르면 fetch가 실행되면서 서버로 요청을 보낸다.

2. 서버로부터 받은 토큰을 localStorage에 저장한다.

3. localStorage에 저장한 토큰을 변수로 저장한다.

4. 변수로 저장된 토큰의 값으로 토큰 유무를 판별하여 조건부 랜더링을 한다.

 

 

 

처음 작성했던 코드 (오류 발생)

const token = localStorage.getItem("TOKEN");

const loginOn = () => {
    fetch("http://10.58.52.169:9001/users/logIn", {
      method: "POST",
      headers: { "Content-Type": "application/json;charset=utf-8" },
      body: JSON.stringify({
        email: inputValues.email,
        password: inputValues.password,
      }),
    })
      .then(res => res.json())
      .then(data => localStorage.setItem("TOKEN", data.accessToken));
      
      token ? setLogIn("") : setLoginWarning("회원정보가 일치하지 않습니다.");

 

1. 로그인 버튼을 누르면 fetch가 실행되면서 서버로 요청을 보낸다.

=> loginOn이라는 함수를 만들고 버튼 onClick이벤트가 발생할 경우 실행되도록 한다.

 

2. 서버로부터 받은 토큰을 localStorage에 저장한다.

 

localStorage.setItem("TOKEN", data.accessToken)

 

3. localStorage에 저장한 토큰을 변수로 저장한다. <- 오류가 발생한 부분

const token = localStorage.getItem("TOKEN");

 

4. 변수로 저장된 토큰의 값으로 토큰 유무를 판별하여 조건부 랜더링을 한다.

token ? setLogIn("") : setLoginWarning("회원정보가 일치하지 않습니다.");

여기서 setLogin("")은 로그인이 완료된 후 로그인 컴포넌트를 user 컴포넌트에서 제거하는 동작을 한다.

setLogin("")이 실행 되면 로그인이 완료된 후 로그인 창이 자동으로 닫힌다.

 

 

 

오류가 발생한 부분

로그인하기 버튼을 클릭하면 loginOn 함수가 실행된다. 

loginOn 함수는 fetch를 실행해서 서버로 사용자가 입력한 값을 넘겨주고 데이터가 일치할 경우 토큰을 넘겨주고

그 토큰을  localStorage에 저장하도록 만들었다.

하지만 로그인하기 버튼을 클릭하고 loginOn 함수가 실행되는 순간 token값을 찾을 수 없다는 오류가 발생했다.

그리고 토큰의 유무로 Warningmessage 또는 로그인창 닫기를 실행 시키는 조건부 랜더링이 바로 실행 되지 않고

새로고침을 해서 다시 랜더링 될 때만 실행되는 오류가 발생했다.

 

 

오류가 발생한 원인 

 아직 토큰 값이 들어오지 않은 상태로 token이 먼저 선언되어 오류가 발생했다.

따라서 토큰의 유무에 따라 실행되어야할 조건부 랜더링도 실행이 되지않았다.

다시 랜더링이 될 때 localStorage에 있던 토큰이 token 변수의 값으로 들어오면서 조건부 랜더링이 실행된다.

토큰값이 바로 변수로 저장되지 않아서 생긴 오류였다.

 

 

해결 방안

 .then(data => {
        localStorage.setItem("TOKEN", data.accessToken);

        if (!localStorage.getItem("TOKEN")) {
          setLoginWarning("회원정보가 일치하지 않습니다.");
        } else {
          setLogIn("");
        }
      });

 

기존에  fetch문에서 localStorage.setItem("TOKEN", data.accessToken) 를 실행한 후에

loginOn함수 밖에서 실행했던 localStorage.getItem("TOKEN")을  fetch문 안에서 조건으로 넣어

조건부 랜더링이 실행되도록 했다.

 

그리고 loginOn함수 밖에 따로 token 변수를 선언하지 않았더니

토큰을 찾을 수 없다는 오류가 해결되었고 조건부 랜더링이 실행되었다.

 

 

수정된 코드

 

 

 


BUT! 또다른 오류 발생!!

 

하지만 조건부 랜더링이 제대로 작동했다면 서버에서 토큰을 보내지 않은 경우,

즉 서버에 일치하는 유저 데이터가 없을 경우에는 setLogin("")이 실행 되지 않고

"회원 정보가 일치하지 않습니다."라는 알림 메세지가 나타나야한다.

그런데 토큰이 없는 유저도 자꾸 로그인이 되는 오류가 발생했다.

 

 

오류가 발생한 부분

토큰의 유무로 조건부 랜더링이 되도록 fetch문 안에 코드를 작성했지만 토큰이 없어도 로그인이 된다.

localStorage를 확인해보니 토큰의 key가 TOKEN으로, value가 undefined로 저장되었다.

 

 

오류가 발생한 원인

 localStorage.setItem("TOKEN", data.accessToken)를 실행 할 때

data.accessToken가 undefined이면  "undefined" 즉, string으로 저장하게 된다. 

 그리고 value로 "undefined"를 가진  TOKEN을 localStorage.getItem("TOKEN")을 하면

undefined를 true 값으로 인식하여 토큰이 있다고 판단하고 로그인이 되어버렸다.

 

 

해결방안

토큰의 값이 undefined일 경우 값으로 인식하지 못하도록 해야했다.

처음에는 단순하게 token != undefined 일 때 로그인이 되도록 조건부 랜더링의 조건을 수정하였다.

그런데 이 방법은 undefined에만 적용되는 조건이기 때문에 만약 서버에서 다른 값이 들어올 경우 대응이 어려웠다.

따라서 undefined 값을 저장한 후 걸러내기보다는

애초에 undefined일 때 토큰값이 저장되지 않도록 하는 것이 우선이었다.

localStorage.getItem()을 수정하는 것이 아닌 localStorage.setItem()를 수정해야 했다.

 

 

변경된 부분

data.accessToken && localStorage.setItem("TOKEN", data.accessToken);

 

그래서 data.accessToken의 값이 존재할 때만(undefined가 아닐 때)

localStorage.setItem("TOKEN", data.accessToken)가 실행되도록 코드를 수정하였다.

 

 data.accessToken이 undefined일 경우  localStorage.setItem()이 실행 되지 않고

TOKEN이라는 key 자체를 저장하지 않게 된다.

따라서 토큰 값이 없는 false로 인식되고 조건부랜더링 역시 정상적으로 작동되었다.

 

 

수정된 코드

 

 

 

최종 수정된 코드

 

 

그리고 이러한 문제가 로그인뿐만 아니라 회원가입에서도 동일하게 발생하여 회원가입도 같은 방식으로 코드를 수정하였다.

 

 

728x90