[React] state as snapshot, batching

프엔개발쟈·2022년 10월 4일
0

state as snapshot

(이벤트 핸들러가 비동기라고 해도) 상태 변수의 값은 렌더시 절대 변하지 않습니다. 렌더시 onClick 내부를 살펴보면,

const [number, setNumber] = useState(0);
// ...
return(
  <button onClick={() => {
        setNumber(number + 5);
        setTimeout(() => {
          alert(number);
        }, 3000);
      }}>+5</button>
  )

number의 value는 setNumber(number + 5)호출 뒤에도 0 입니다. 리액트가 컴포넌트를 호출하여 UI의스냅샷을 찍을 때 value는 고정되어 있습니다(fixed)

batching

사전: 일괄 처리

웨이터가 주문을 받을때를 생각해봅시다. 주문하나 받고 음식을 가져다주지 않고, 여러가지 주문을 한꺼번에 받고 나중에 음식을 가져다 줍니다.

이렇게 하면, 리렌더링을 계속하지 않고도 많은 컴포넌트의 많은 변수를 한꺼번에 업데이트 할 수 있습니다. 하지만, 이건 이벤트 핸들러나 안의 코드가 끝나지 않았다면 UI가 업데이트 되지 않는다는 것을 의미합니다. 이를 batching 이라고 합니다.

다음 렌더 전에 같은 값을 여러번 업데이트 하고 싶다면?

다음 값을 전달하지 않고, 큐(queue)에 있던 이전 값을 기반으로 다음 상태를 계산할 수 있는 함수를 넣으면 됩니다.

//이전
 <button onClick={() => {
        setNumber(number + 1);
        setNumber(number + 1);
        setNumber(number + 1);
      }}>+3</button>
//이후
 <button onClick={() => {
        setNumber(n => n + 1);
        setNumber(n => n + 1);
        setNumber(n => n + 1);
      }}>+3</button>

동작

  1. 리액트는 이벤트 핸들러에있는 다른 코드를 모두 실행하고, 해당 함수를 리액트 큐에 넣습니다.
  2. 다음 렌더링에, 리액트는 큐를 모두 확인하고, 마지막으로 업데이트된 상태를 줍니다.
    참고

새로운 값을 넣고 업데이트를 한다면?

  <button onClick={() => {
        setNumber(number + 5);
        setNumber(n => n + 1);
      }}>Increase the number</button>

동작

  1. setNumber(number + 5): number는 0이기 때문에, setNumber는 (0+5)가 되고, 리액트는 "5로 바꾸기"를 큐에 넣습니다.
  2. setNumber(n => n + 1): n => n + 1 는 업데이트 함수입니다. 리액트는 이를 큐에 넣습니다.

참고:
https://beta.reactjs.org/learn/state-as-a-snapshot
https://beta.reactjs.org/learn/queueing-a-series-of-state-updates

0개의 댓글