setState가 생각한대로 작동하지 않는 이유

sebiin·2022년 6월 21일
0
post-thumbnail

React에서는 컴포넌트 안의 상태 값을 관리하기 위해 useState 함수를 사용한다. useStateconst [state, setState] = useState();와 같이 state라는 변수와 setState()라는 해당 값을 변경하는 함수로 구성된다.

평소처럼 useState를 사용하던 중, setState()가 생각한대로 작동하지 않는 문제를 발견하였다. 하나의 setState()를 한 번에 여러번 요청하면 마지막에 요청된 setState()만 수행하는 것처럼 작동하는 것이다.

왜 이런 문제가 발생하는 것일까?

📌setState는 비동기 함수

결론적으로 말하자면 setState() 호출은 비동기적으로 이루어지기 때문이다.

import { useState } from "react";

function App() {
  const [number, setNumber] = useState(0);

  const plusNumber = () => {
    setNumber(number + 1);
    setNumber(number + 1);
    setNumber(number + 1);
  }

  return (
    <div>
      <p>{number}</p>
      <button onClick={plusNumber}>+3</button>
    </div>
  );
}

export default App;

위의 코드를 보면 +3버튼을 눌렀을 때, number가 3씩 증가할 것이라고 예상된다.

하지만 예상과는 다르게 1씩 증가하는 것을 확인할 수 있다.

why?

setState()는 컴포넌트의 state 객체에 대한 업데이트를 실행한다. state가 변경되면, 컴포넌트는 리렌더링된다.

또한, 모든 컴포넌트가 자신의 이벤트 핸들러에서 setState()를 호출할 때까지 React는 리렌더링을 하지 않고 내부적으로 기다리고 있다. 이를 통해 불필요한 렌더링을 방지하면서 성능을 향상시킨다.

React는 상태 값을 업데이트 할 때 모든 요청에 따라 바로바로 rerender가 되는것이 아닌 변경사항을 모아서 한번에 일괄 처리(batch update)를 하고, 이 일괄 업데이트를 통해 컴포넌트의 렌더링 횟수를 최소화하는 것이다.

따라서 위의 코드에서 1씩 증가하는 것처럼 보이는 결과가 나타난 것은, setNumber()number+1이 수행된 결과 값이 아닌 number 값이 들어가기 때문이다. number가 0일 때 버튼을 누르면 setNumber()에 각각 0, 1, 2가 아니라 모두 0이 들어가므로 결과적으로 +1이 되서 마지막 함수만 수행된 것처럼 보이는 것이다.

📌setState를 동기적으로 처리하는 방법

setState()가 가장 최신의 state 값을 사용하는 방법으로는 setState() 에 객체 대신 함수를 전달하는 것이 있다.

updater 함수를 전달하면 updater 함수 안에서 이전 state 값에 접근할 수 있다. setState() 호출은 일괄적으로 처리되기 때문에 여러 업데이트 사항이 충돌 없이 차례대로 반영되도록 한다.

const plusNumber = () => {
    setNumber(num => num + 1);
    setNumber(num => num + 1);
    setNumber(num => num + 1);
  }

함수로 넘겨주니 제대로 동작한다!


📕 참조

profile
초보개발자

0개의 댓글