React가 더 나은 성능을 위해 여러 개의 state 업데이트를 한 번에 리렌더링으로 묶어서 진행하는 것
//해당 코드는 1씩 증가
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>
</>
)
}
//해당 코드는 3씩 증가
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
//아래의 작업은 모두 일괄적으로 묶여 처리된다. 한 번의 리렌더링만 발생한다.
setNumber(n => n + 1);
setNumber(n => n + 1);
setNumber(n => n + 1);
}}>+3</button>
</>
)
}
예제 1 코드와 예제 2 코드 모두 버튼 클릭 시 3씩 증가하도록 useState를 사용해 작성하였다.
그러나 예제2 코드는 잘 동작하는 반면, 예제1 코드는 비동기처럼 마지막 setNumber만 실행된 것처럼 보여진다.
이러한 이유는 무엇일까?
이러한 이유는 batch에 존재한다.
예제 1
예제 2
export function getFinalState(baseState, queue) {
let finalState = baseState;
for (let update of queue) {
if (typeof update === 'function')
finalState = update(finalState);
else
finalState = update;
}
return finalState;
}
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 9);
setNumber(number + 5);
setNumber(n => n + 1);
}}>Increase the number</button>
</>
)
}
setNumber(number + 9)
⇒ number에 9를 더한 값으로 바꾸기
setNumber(number + 5)
⇒ number에 5를 더한 값으로 바꾸기
setNumber(n => n + 1)
⇒ 이전 큐에 있는 값에서 1을 더하기
⇒ (number + 5) +1
결과 : 6
import { flushSync } from "react-dom";
function handleClick() {
// React 는 flushSync 메서드가 실행되는 즉시 DOM을 업데이트 한다.
flushSync(() => {
setCounter((c) => c + 1);
});
// React 는 flushSync 메서드가 실행되는 즉시 DOM을 업데이트 한다.
flushSync(() => {
setFlag((f) => !f);
});
}
// 따라서 해당 함수가 실행될 경우 React는 총 두 번의 리렌더링을 수행한다.
https://react.dev/learn/state-as-a-snapshot