useState 어디까지 알고 있니?

Wynter24·2023년 8월 31일

개념을 잘못 이해했다는 것을 깨닫게 된 시점

추가, 삭제 버튼이 있는 Todo List 프로젝트를 진행하며 useState에 대해 잘못 이해하고 있다는 것을 알았다(정확히는 setState에 관한 것이다)

다음은 기존 코드와 리펙토링한 코드이다.

My ToDo List
My ToDo List 리팩토링

간략하게 말하자면 working zone에서 클릭한 게시물이 보이지 않게 하기 위해 filter를 썼다. 그것보다는 애초에 working, done zone에 게시물이 보이는 (html)위치에 filter를 걸어주면 된다. 그리고 완료 버튼 클릭 시 실행되는 메서드로 filter 대신 map을 사용하였다.
단순히 클릭한 게시물 정보 하나만 바꾸어 추가하면 되겠다고 생각했는데 setState는 기존의 전체 데이터를 하나의 데이터로 교체한다는 사실을 간과하가 있었다.
setState를 하면 기존 state 전체가 내가 입력한 값으로 바뀌므로 map을 사용하여 전체를 다시 반환하되 특정 객체의 정보만 변경하여 새로운 배열에 담아주어 반환하여 이 같은 문제를 해결하였다.


useState의 동기와 비동기

1. setState 작동방식 - 비동기식처리

setState가 연속으로 호출되면 batch update 후 실행된다.

batch update : 리액트 성능을 위해 여러개의 state 업데이트를 하나로 묶어서 리렌더링한다.

2. 비동기 작업

import { useState } from "react";

export default function App() {
  const [num, setNum] = useState(0);

  const plueOne = () => {
    setNum(num + 1);
    console.log(num);  // 0이 출력됨.
  };
  return (
    <div>
      <p>{num}</p>
      <button onClick={plueOne}>+</button>
    </div>
  );
}
  • 의도: num+1이 된 값, 즉 1을 출력하려고 했다.
  • 이유: setState 함수가 비동기적으로 작동하기 때문에 업데이트 되기 전의 num 값(0)이 출력된다.

3. 함수형 업데이트

setState 함수에 state값을 인자로 넘기는 콜백 함수를 사용해 값을 업데이트하면 위의 문제를 해결 할 수 있다.

import { useState } from "react";

export default function App() {
  const [num, setNum] = useState(0);

  const handlePlus = () => {
    setNum((num) => num + 1);
    setNum((num) => num + 1);
    setNum((num) => num + 1);
  };
  return (
    <div>
      <p>{num}</p>
      <button onClick={handlePlus}>plus</button>
    </div>
  );
}

이처럼 함수형 업데이트를 사용하면 업데이트된 state값을 인자로 받기 때문에 원했던 결과를 얻을 수 있다.


정리

setState hook의 update 함수의 2가지 방법

① setNumber(value) // 직접 값 변경
② setNumber(callback) // 함수를 통한 변경(동기화처리)

※ callback 함수를 인자로 작동되는 함수들은 모두 동기식으로 작동한다.

setState update를 할 때 batch update와 setState가 비동기식처리 한다는 것을 주의하며 함수형 업데이트를 이용하여 동기화 처리를 한다. 이를 통해 원하는 결과를 얻을 수 있다.


참고자료
useState 비동기
[React] useState batching, 비동기, 동기처리

profile
내가 다시 보려고 쓰는 개발.log

0개의 댓글