오늘의 오류

useState에 의해 갱신 객체가 제대로 합쳐지지 않는 오류

삐옹 2022. 7. 20. 04:16

무엇이 문제인가?

서버로부터 데이터 리스트를 받아와 성공 처리로 3가지 카테고리로 나누어 각각의 state에 갱신했다.

그러면 각각의 저장된 state값을 화면에 map을 돌려 뿌려주면 되는 상황.

 

문제가 발생한 이유는 무엇인가?

useEffect에 의해 첫 마운트 후 데이터 리스트를 받아와

map안에 switch문을 돌려 미리 만들어놓은 각 카테고리 state 별로 갱신해주었다.

데이터 리스트에는 내가 생성한 23개의 데이터가 분명 쌓여있는데..

새로 고침을 눌러도 분명 잘 남아있는데..

각 카테고리 state에는 가장 최근에 추가한 데이터 단 한개만 들어온다.

그래서 화면에는 초라하게도 1개의 데이터만이 보인다.

 

시도해 본 것

  1. 데이터 생성 후 새로고침하면 데이터 갯수가 1개 추가되어 있는가? ✅
  2. 데이터 삭제 후 새로고침하여 데이터 갯수가 1개 줄어있는가? ✅
  3. 새로고침 후 각 카테고리 리스트 콘솔 찍어보기 ✅   -> 너구나?🧐

리스트는 잘 받아지니, switch 문 마다 콘솔을 찍어보았다.

  const [todoBoardList, setTodoBoardList] = useState([]);
  const [inProgressList, setInProgressList] = useState([]);
  const [doneList, setDoneList] = useState([]);
...
.then((res) => {
        const allBoardList = res.data.posts;

        console.log(allBoardList); // (23) [ {...}, {...}, ... ]
        
        // Categorize all board data by the 3 categories
        allBoardList.map((board) => {
          switch (board.category) {
            case "todo":
              console.log("---todo 카테고리---"); // x 17
              setTodoBoardList([...todoList, board]);
              break;
            case "inProgress":
              console.log("---inProgress 카테고리---"); // x 2

              setInProgressList([...inProgressList, board]);
              break;
            case "done":
              console.log("---done 카테고리---"); // x 1

              setDoneList([...doneList, board]);
              break;
            default:
              console.log("데이터를 불러오는데 실패했습니다.");
          }
        });
      })
 ...

map으로 돌려 각 조건의 실행문에서 찍어준 콘솔은 갯수에 맞게 잘 찍히는걸 보고,

setState에 의해 문제가 있음을 확신했다.

react 공식문서에서 useState 관련 내용을 정독해보다보니.

이런 내용이 있었다.

나는 객체를 업데이트 하기 위해 이전 state값을 객체 전개 연산자를 이용해 새로운 데이터와 결합하여 set함수를 실행시켰다.

그래야 react에서 변경을 감지 할 수 있기 떄문에.

setTodoBoardList([...todoList, board]);

그런데 여기서 드는 의문점 하나.

setState의 특성을 잘 생각해보면 업데이트가 바로 일어나지 않고 렌더링이 한 번 일어난 후 state에 업데이트가 된다.

mapping 시작 -> setState, break -> mapping ->  setState, break -> ... -> setState, break -> mapping 종료

setState 때마다 리렌더링이 일어났을 것이고[...todoList, board] 값이 업데이트 되었을 것이다.

그렇다면 내 추측으론 적어도 실제 데이터 갯수보다 하나가 적은 todoList의 값이 반환되어야하는데.

왜 마지막 것만 하나 담겨서 반환된 것인지 아직 이유를 잘 모르겠다. -> 낼 질문방에 올려보자

 

일단 이전의 값 업데이트를 확실히 보장만 시켜준다면 가능하지 않을까 싶어

그런 비동기 문제를 해결해주는 함수형 업데이트를 써보았다.  

setTodoBoardList((prevState) => {
	return [...prevState, board];
});

옴마야.

 

바로 된다고??

 

🙇🏻참고한 글

https://mingule.tistory.com/64

 

React에서의 setState

React에서 Functional Component를 사용하면 useState hook을 정~말 많이 사용하게 된다. 그 중, 프로젝트를 하면서 setState를 사용하면서 들었던 두 가지 의문점과, 이를 해결해나가는 과정 그리고 그에 관한

mingule.tistory.com