memo기능 버그

noungheeya·2022년 11월 26일
0

project

목록 보기
5/10

이 글은 정보 전달이 아닌 공부 하며 느낀 것을 정리하는 글입니다😀


  • MEMO 버튼을 클릭하면 메모를 볼 수 있다.
  • 편집을 클릭하면 메모 내용을 변경할 수 있다.
  • 편집 후 메모 화면에 문구가 바뀐다.
  • close 버튼을 닫으면 메모 ui가 사라진다.

이렇게 기능을 구성했지만 close 버튼을 클릭하면 변경한 메모 내용이 아닌 이전 메모 화면이 다시 화면에 나타나는 문제가 발생했다.

코드구성

*PinedListTab.tsx
PinedListBox.tsx return값

컴포넌트를 하나의 프린트기 박스라는 가정하에 그림으로... 표현하면..

이렇게 그렸다!😂

PinedListTab.tsx 에서 하는 일

  1. useQueryClient를 사용하여 저장된 쿼리값('list'object)을 받아온다.
  2. 그 값을 return에서 호출한 PineListBox컴포넌트에 전달해준다.

PinedListBox.tsx 에서 하는 일

  1. 부모 컴포넌트인 PinedListTab에서 'list object' 값을 받는다
  2. 그 값을 사용하여 ReactDom을 반환해준다.

PinedListBox안에서의 상태변화

이곳에서 3가지의 상태변화가 일어난다
1. 'memo'버튼 클릭 시: memoState 값의 저장된 boolean 값이 변경되어 ui 구조가 메모 값을 볼 수 있도록 변화함
2. '편집'버튼 클릭 시: editState 값의 저장된 boolean 값이 변경되어 ui 구조가 메모 내용을 편집할 수 있는 폼 구조로 변화함
3. 폼 구조 안에서 입력 시: contentStat 값의 저장된 내용이 변경되어 서버로 보내진 후 list 객체 안에 memo 값이 변경됨 그리고 화면에 나타나야 할 값임

문제원인

그림에서 보면 state값이 변화하면 컴포넌튼 함수는 재호출되며 리렌더링이 발생한다.
state값의 변화는 하위 컴포넌트인 PinedListBox에서 발생된다. 만약 상위 컴포넌트가 리렌더링 되면 하위 컴포넌트까지 리렌더링 되지만 하위 컴포넌트에서만 리렌더링 될 경우 상위 컴포넌트는 그대로이다. 즉 서버에 보내진 list.memo값이 변경되더라도 상위컴포넌트에서는 리렌더링이 발생되지 않아 이전 값을 유지하여 값이 바뀌지 않는다.


코드를 자세히 살펴보면 메모칸에 보여져야 하는 값이 변화되는 state값이 아닌 상위컴포넌트에서 받은 list객체의 memo값이였다.

해결방법

방법은 아주 간단하다 change 이벤트와 submit 이벤트에서 사용한 content state 값을 사용하면 된다.

지금 생각해 보면 아주 기본적이 문제 였다ㅠㅠ 프런트엔드에서 상태 관리가 중요하다는 걸 이 버그를 통해 더 잘 느꼈다
그런데... 이 문제 원인을 찾다 궁금한 점이 생겼다!

또다른 궁금증

서버에서 받아오는 값을 관리하기 위한 방법으로 react-query를 사용했다. 이유는 쿼리키를 통해 관리하는 것이 localStorage와 비슷하고 마치 사물함에서 물건 찾는 것과 같은 느낌이 들어서 초보자에게 편리해 보였기 때문이다.
또한 옵션 값으로 staleTime을 Infinity로 설정하면 서버에서 받아온 데이터 값을 유지하여 계속해서 값을 받아오지 않아 불필요한 통신을 줄일 수 있다. 또한 사용자가 값을 변경하거나 삭제하면 invalidateQueries 통해 새로운 데이터를 받아올 수 있게하는 편리한 기능도 있다.
그래서 바로 변경하게 할 수 있도록 invalidateQueries를 사용했는데 왜 바끼지 않았을까??

이유는 PindListTab에서 이미 서버에서 불러와서 저장된 쿼리 값을 사용했기 때문이다!


*useGetData()는 쿼리값들을 모아둔 커스텀hook함수

다른 컴포넌트에서 사용해야할 이유가 있어서 더 상위 컴포너트에서 useQuery를 사용했기 때문에 pinedListTab에서는 저장한 쿼리 키를 호출했다.
그런데 앞에서 언급한 내용처럼 staleTime을 infinity로 할경우 서버에서 받아오지는 않는다.

저장된 쿼리를 사용하지 않고 useQuery를 사용해서 콘솔로 찍어낸 값과 그렇지 않은 값을 비교해보자!
*useGetPinedList()는 useQuery를 반환하는 커스텀 훅 함수


useQuery가 아닌 저장된 쿼리값을 사용한 경우는 하위 컴포넌트의 state 값이 변경되어도 렌더링이 발생하지 않기 때문에 콘솔이 하나밖에 안 찍힌다.
또한 초기 값이기에 memo 값이 존재하지 않는다.



useQuery 값을 사용한 경우는 콘솔이 두 개 찍히며 memo 값이 변경됨을 알 수 있다!
그럼 PinedListBox 컴포넌트에서 state 값이 아닌 props 값이 list 객체를 사용하고
PinedListTab에서 useQuery를 사용하면??

........안된다... ㅋㅋㅋㅋㅋ 리페치는 되지만 화면에 나타내어야 할 값은 state로 담아야 하는 거 같다. 우선 이부분에 대한 궁금증은 다음에....

profile
귀여븐 엥팁이지롱😊

0개의 댓글