[Toy Project] Todo List 일지 2 : state 설정

0
post-thumbnail

GoalReminder 컴포넌트 의도

  • 오늘의 목표를 세울 때 달별 목표 설정한 것을 상기시키기 위함
    -> 서버에서 GET 메서드로 Data 요청 후 화면에 렌더링

문제발생

  1. 응답 받은 데이터를 console.log()로 확인했지만 JSX에 적용하려고하면 에러가 발생
  2. 에러메세지에는 '7'(date.getMonth() 관련)에 undefined로 적용되어 뒤에 프로퍼티 조회하는데 문제가 발생한 것으로 안내됨
  • 추정1 : 하위 컴포넌트에서 fetch가 적용되어 로딩 문제가 발생
  • 추정2 : then() 내부에서 monthGoals에 재할당이 이루어지지 않음

해결 1. 처음부터 한줄씩 다시 코드를 확인

추정한 2가지 요인만 생각하고 해당 부분만 수정을 반복하면서 오류가 잡히지 않았다. 한참을 고민하다가 어떻게 접근해야할지 막막하던 차에 차분하게 한줄씩 다시 읽어보기로 했다. 한줄씩 보면서 실마리가 잡혔다. 갑자기 할당없이 선언한 변수(위의 사진의 monthGoals )를 보고 이걸 왜 사용했는지 다시 생각해보았다.

let이나 const는 블록 스코프를 가진다!

프로미스를 반환하는 fetch 로 서버에서 데이터를 받아왔기 때문에 async& await 키워드를 사용하지 않는한 then 메서드 내부에서만 데이터를 저장하고, 확인할 수있다.
컴포넌트 함수의 return 값의 JSX에서 데이터를 <div> 의 텍스트로 사용하기 위해서 외부에서 변수 선언만 하고, then 내부에서 재할당 하는 방식으로 적용했다.

여기가 문제였다. 재할당이 아닌 일반 변수로 적용한게 원인이었다.


해결 2. 단순 변수에서 state로 변경

state는 (1)이벤트에 의해 (2)변화되는 값

  • fetch도 이벤트

단순하게 onClick, onSubmit 같은 것들만 이벤트라고 생각했었다. 그리고 한번 DB에서 받아오면 수정(2)이 되지 않기 때문에 state가 아닌 일반 변수로 사용하려고 했던 것이 이번 오류의 핵심이었다.
fetch(1)로 서버에서 응답 받으면 사용자에 의해 상태가 변경(2-1) 되지 않아도 고정된 값이 아니다(2-2). 상호작용으로 변경되는 값만 state로 적용해야하는 것이 아니었다.
이점을 인지하고 let monthGoals; 대신 useState를 적용하여 해결했다.

const [reminder, setReminder] = useState("")

// ... 생략 ... fetch() 
.then((monthDatas) => {
    setReminder(monthDatas[date.getMonth()].monthlyGoal);
})

// ... 생략 ... return
<div className={reminder === "" ? "reminder emptyed" : "reminder"}>
    {(reminder === "") ? 
      "Your month goal is empty" : reminder}
</div>

요약

  • fetch로 받아온 데이터는 state로 관리한다.
  • 에러 원인이 잘 보이지 않을 때는 처음부터 차근차근 코드를 분석한다.

0개의 댓글