githubEdit

state 업데이트 큐

state 변수를 설정하면 다음 렌더링이 큐에 들어갑니다. 그러나 때에 따라 다음 렌더링을 큐에 넣기 전에, 값에 대해 여러 작업을 수행하고 싶을 때도 있습니다. 이러한 경우 React state batches 업데이트를 활용하면 됩니다.

React state batches 업데이트

import { useState } from "react";

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button
        onClick={() => {
          setNumber(number + 1);
          setNumber(number + 1);
          setNumber(number + 1);
        }}
      >
        +3
      </button>
    </>
  );
}

우리는 이 코드에서 setNumber(number + 1) 를 3번 호출하기 때문에 버튼을 누르면 3씩 증가할 것으로 예상할 수 있습니다.

그러나 실제 결과 값은 1 씩 증가하는 것을 알 수 있습니다.

image

이전 세션에서도 이야기했 듯 각 렌더링의 state 값은 고정되어 있으므로, 첫 번째 렌더링의 이벤트 핸들러의 number 값은 setNumber(0 + 1) 를 몇 번 호출하든 항상 0입니다.

React는 state 업데이트를 하기 전에 이벤트 핸들러의 모든 코드가 실행될 때까지 기다립니다.

따라서 리렌더링은 모든 setNumber() 호출이 완료된 이후에만 일어나고, 여러 번 setState()를 호출하더라도 마지막 값만 기록해 최종 상태로 반영합니다.

즉, 위와 같은 코드를 실행했을 때, 결과적으로 setNumber(number+3) 코드의 결과 값만 최종 상태로 반영된다는 것입니다.

Batching

  • Batching은 여러 state 업데이트를 한 번에 처리하여 리렌더링 횟수를 줄이는 것입니다.

  • 이벤트 핸들러 실행 중에는 UI가 업데이트되지 않아 반쯤 완성된 상태의 렌더링을 방지합니다.

  • React는 안전한 경우에만 batching을 수행합니다. 예를 들어 의도적인 여러 이벤트(클릭 등)은 각각 개별적으로 상태를 업데이트 합니다.

  • Batching을 활용하면 여러 컴포넌트의 다수 state 변수를 효율적으로 업데이트 할 수 있고, 불필요한 렌더링을 피할 수 있습니다.

다음 렌더링 전에 동일한 state 변수를 여러 번 업데이트하기

흔한 사례는 아니지만 다음 렌더링 전에 동일한 state 변수를 여러 번 업데이트 하고 싶다면 setNumber((n) ⇒ n + 1)과 같이 이전 큐의 state를 기반으로 다음 state를 계산하는 함수를 전달할 수 있습니다.

**setNumber((n) ⇒ n + 1)**과 같은 함수를 업데이터 함수라고 부릅니다.

아래 코드처럼 setNumber에 업데이터 함수를 인자로 넘겨주게 된다면, 마치

setNumber(setNumber(setNumber(n+1)+1)+1) 처럼 동작하게 됩니다.

React가 이벤트 핸들러를 수행하는 동안 여러 코드를 통해 작동하는 방식은 다음과 같습니다.

  1. setNumber(n => n + 1): n => n + 1 함수를 큐에 추가합니다.

  2. setNumber(n => n + 1): n => n + 1 함수를 큐에 추가합니다.

  3. setNumber(n => n + 1): n => n + 1 함수를 큐에 추가합니다.

queued update

n

returns

n => n + 1

0

0 + 1 = 1

n => n + 1

1

1 + 1 = 2

n => n + 1

2

2 + 1 = 3

때문에 위의 코드를 실행했을 때 3씩 증가하게 됩니다.

state를 교체한 후 업데이트하면 어떻게 되나요?

위 코드의 경우는 아래와 같은 큐를 가지게 됩니다.

queued update

n

returns

”replace with 5

0 (unused)

5

n => n + 1

5

5 + 1 = 6

업데이트 후 state를 바꾸면 어떻게 되나요?

  1. setNumber(number + 5): number0 이므로 setNumber(0 + 5)입니다. React는 5로 바꾸기” 를 큐에 추가합니다.

  2. setNumber(n => n + 1): n => n + 1 는 업데이터 함수입니다. React는 이 함수를 큐에 추가합니다.

  3. setNumber(42): React는 42로 바꾸기” 를 큐에 추가합니다.

다음 렌더링하는 동안, React는 state 큐를 순회합니다.

queued update

n

returns

”replace with 5

0 (unused)

5

n => n + 1

5

5 + 1 = 6

”replace with 42

6 (unused)

42

그런 다음 React는 42를 최종 결과로 저장하고 useState에서 반환합니다.

명명 규칙

업데이터 함수 인수의 이름은 해당 state 변수의 첫 글자로 지정하는 것이 일반적입니다.

좀 더 자세한 코드를 선호하는 경우 setEnabled(enabled => !enabled)와 같이 전체 state 변수 이름을 반복하거나, setEnabled(prevEnabled => !prevEnabled)와 같은 접두사를 사용하는 것이 널리 사용되는 규칙입니다.

Last updated