정답: count는 1씩 증가한다.

you clicked 0 times

특정 렌더링의 count는 시간에 따라 변하는 것이 아니라, 각 렌더링마다 상수로서 존재한다. 컴포넌트가 다시 호출되면 새로운 렌더링 안에서 다시 count값이 상수로서 존재하게 된다.


// prettier-ignore
function Counter() {
  const [count, setCount] = useState(0);
 
  return (
    <div>
      <p> you clicked {count} times </p>
      <button onClick={() => {setCount(count + 1)}}> increase count </button>
    </div>
  );
}

리액트를 처음 배우게 되면 아마도 가장 신비하게 느껴지는 것이 바로 useState훅일 것이다. 어떻게 setCount함수 만으로 count의 값이 변경되고, 자동으로 컴포넌트에 반영되어 화면에 보이는 것일까? count변수는 사실 굉장히 복잡한 함수 또는 객체로 구현되어 있어서 setCount 함수를 호출할 때마다 자동으로 값이 바뀌는 것일까?

그렇지 않다. count변수는 그저 숫자이다. Counter 컴포넌트가 처음으로 렌더링될 때 count 변수에는 useState 함수에서 가져온 값 0이 담기며, 따라서 처음으로 렌더링된 Counter 컴포넌트는 정확히 아래와 같다.

// prettier-ignore
function Counter() {
  const count = 0;
 
  //...
  <p> you clicked {count} times </p>
  //...
}

여기서 버튼을 한 번 누르면 함수가 다시 호출되고, 숫자 count의 값이 바뀐다.

// prettier-ignore
function Counter() {
  const count = 1;
 
  //...
  <p> you clicked {count} times </p>
  //...
}

버튼을 한 번 더 눌러도 마찬가지이다.

// prettier-ignore
function Counter() {
  const count = 2;
 
  //...
  <p> you clicked {count} times </p>
  //...
}

count변수는 각 렌더링 안에서 변하지 않는 상수이다. <p> you clicked {count} times </p>가 하는 일은 단지 숫자 count를 렌더링 결과 안에 포함시키는 것 뿐이다. (이 값은 리액트를 통해 제공된다.)

이제 원래의 문제를 다시 보자. count의 값이 가령 20이라고 가정하면 해당 렌더링에서의 컴포넌트는 아래와 같다.

function Counter() {
  const count = 20;
 
  return (
    <div>
      <p> you clicked {count} times </p>
      <button
        onClick={() => {
          setCount(count + 1); // setCount(20 + 1);
          setCount(count + 1); // setCount(20 + 1);
        }}
      >
        increase count
      </button>
    </div>
  );
}

결국 버튼을 눌러도 setCount(21)만 두 번 실행될 뿐이므로 버튼을 누를 때 마다 count의 값은 1씩 증가하는 것이다.

만약 count가 2씩 증가하도록 하고 싶다면, 다음과 같이 nextState 대신 update function을 인수로 넘겨주면 된다.

function Counter() {
  //...
  <button
    onClick={() => {
      setCount((count) => count + 1); // setCount(20 => 21);
      setCount((count) => count + 1); // setCount(21 => 22);
    }}
  >
    increase count
  </button>;
  //...
}

참고자료