setState() 관련 동작

jYur·2023년 2월 22일
0

나만의 설명

목록 보기
11/11

( 2024-02-19 보완 )

배운 지 얼마 되지 않았을 때 상태 값을 업데이트하는 함수(예: 아래 예시의 setCount())가 호출될 때마다 즉시 함수 컴포넌트가 다시 실행되는 것이라 오해한 적이 있었다.

아래 실제 코드와 함께 동작을 알아보자.
+ 버튼을 클릭할 때마다 카운트가 3씩 증가하는 카운터를 구현한 코드다.

function Counter() {
  console.log("Counter() 시작");
  const [count, setCount] = React.useState(0);
  console.log(`count: ${count}`);
  
  const onClick = () => {
    console.log("setCount() (1/3)");
    setCount((cur) => {
      console.log("count 1 증가 (1/3)");
      return cur + 1;
    });

    console.log("setCount() (2/3)");
    setCount((cur) => {
      console.log("count 1 증가 (2/3)");
      return cur + 1;
    });

    console.log("setCount() (3/3)");
    setCount((cur) => {
      console.log("count 1 증가 (3/3)");
      return cur + 1;
    });
  };
  
  console.log("Counter() 끝");
  return (
    <>
      <h1>{count}</h1>
      <button
        onClick={onClick}
      >
        +
      </button>
    </>
  );
}

[ 콘솔 출력 ]

  1. 최초 렌더링
Counter() 시작
count: 0
Counter() 끝
  1. + 버튼 첫 번째 클릭
setCount() (1/3)
count 1 증가 (1/3)
setCount() (2/3)
setCount() (3/3)
Counter() 시작
count 1 증가 (2/3)
count 1 증가 (3/3)
count: 3
Counter() 끝
  1. + 버튼 두 번째 클릭
setCount() (1/3)
setCount() (2/3)
setCount() (3/3)
Counter() 시작
count 1 증가 (1/3)
count 1 증가 (2/3)
count 1 증가 (3/3)
count: 6
Counter() 끝
  1. + 버튼 세 번째 클릭
setCount() (1/3)
setCount() (2/3)
setCount() (3/3)
Counter() 시작
count 1 증가 (1/3)
count 1 증가 (2/3)
count 1 증가 (3/3)
count: 9
Counter() 끝

Q. 위 출력 결과를 보고 무엇을 알 수 있을까?
A.

  • 첫 번째 setCount() 함수를 호출하자마자 Counter() 컴포넌트가 즉시 다시 렌더링되는 것이 아니라 같은 스코프에 있는 setCount() 함수들을 전부 호출한 뒤에 렌더링이 시작된다.
  • 다시 렌더링될 때 useState() 함수 호출 시점에 count 값이 변경된다. (그래서 useState()를 컴포넌트 코드 최상단에 위치시켜야 하는 것이군)

Q. 파라미터 cur이 아니라 count를 직접 변경하면 어떻게 될까?

const onClick = () => {
  // setCount(count + 1);과 같음
  setCount(() => {
    return count + 1; // 파라미터 대신 count 기준 +1
  });
  
  setCount(() => {
    return count + 1;
  });
  
  setCount(() => {
    return count + 1;
  });
};

A. 3씩 증가하는 게 아니라 1씩 증가한다.

  • count + 1 반환 전에 count 값을 출력해 보면 세 곳에서의 값이 같다. 즉, count에 1 더한 값이 계속 반복 할당될 뿐이다.
  • 위에서 출력 결과로 보았듯, 상태 변경을 전부 처리한 뒤에야 최종적으로 변경된 값을 count에 할당하는 것이라면 변경을 처리하는 동안 count 값에 변화가 없는 것은 당연하다.

Q. setCount()를 호출하지만 상태를 변경하지는 않는다면 어떻게 될까?
A. setCount()를 호출하더라도 상태 변경이 없으면 함수 컴포넌트는 다시 렌더링 되지 않는다.

Q. 첫 번째 클릭만 출력이 다른 건 왜일까?
카운터를 두 개 만들어서 번갈아가며 클릭해 보면, 꼭 첫 번째 클릭이 아니더라도 직전에 다른 카운터의 버튼을 클릭했다면 첫 번째 클릭했을 때와 출력이 같던데, 흠..

0개의 댓글