⚙️ state 업데이트 큐
state 변수를 설정하면 다음 렌더링이 큐에 들어간다.
예제 코드
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>
</>
)
}
https://codesandbox.io/p/sandbox/tty55g?file=%2Fsrc%2FApp.js
각 렌더링의 state 값은 고정
→ 첫 번째 렌더링의 이벤트 핸들러의 number 값 setNumber(1)을 몇 번 호출하든 항상 0
🖥️ batching
batching ? 여러 번의 state 업데이트를 하나로 묶어서 처리하는 과정, 여러 업데이트를 효율적으로 처리하게 해줌
- React는 클릭과 같은 여러 의도적인 이벤트에 대해 batch를 수행하지는 않으며, 각 클릭은 개별적으로 처리됨
ex) 음식점에서 웨이터가 여러 주문을 한꺼번에 주방에 전달하는 상황
- batching으로 인해 setNumber(number + 1)을 여러 번 호출해도, 각 호출이 개별적으로 렌더링을 일으키지 않고, 최종적인 state 변경 사항만 반영된다.
- 위의 예시 코드의 경우, 한 번의 렌더링이 발생하지만, state가 갱신된 이후의 값을 고려하지 않고 같은 값을 참조하는 문제가 발생한다.
🖥️ 업데이터 함수 (updater function)
업데이터 함수 (updater function) ? 현재의 state 값을 기반으로 새로운 값을 계산하는 함수
- batch 처리 중에도 정확하게 이전 상태를 반영해 업데이트할 수 있도록 도와준다. → 같은 값 참조 문제 해결
- 다음 렌더링 전에 동일한 state 변수를 여러 번 업데이트하고 싶다면 이전 큐의 state를 기반으로 다음 state를 계산하는 함수를 전달하면 된다.
작동 과정
- React는 이벤트 핸들러의 다른 코드가 모두 실행된 후에 이 함수가 처리되도록 큐에 넣는다.
- 다음 렌더링 중에 React는 큐를 순회하여 최종 업데이트된 state를 제공한다
예제 코드
setNumber(number + 1) 대신 setNumber(n ⇒ n + 1) 사용
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>
</>
)
}
https://codesandbox.io/p/sandbox/xcsmmf?file=%2Fsrc%2FApp.js
이때 setNumber(n ⇒ n + 1)가 updater function !!
이벤트 핸들러에서 여러 setNumber(n => n + 1) 호출이 발생하면, React는 각 호출을 큐에 저장한다.
- setNumber(n => n + 1): n => n + 1 함수를 큐에 추가합니다.
- setNumber(n => n + 1): n => n + 1 함수를 큐에 추가합니다.
- setNumber(n => n + 1): n => n + 1 함수를 큐에 추가합니다.
React는 렌더링할 때 현재 number 상태값(여기서는 0)을 첫 번째 함수에 n으로 전달한다.
이후 각 함수 호출 결과를 순차적으로 다음 함수에 n으로 전달하여 최종 값을 계산한다.
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 |
⇒ React는 3을 최종 결과로 저장하고 useState에서 반환한다.
🖥️ state를 교체한 후 업데이트하면 어떻게 되나요?
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
setNumber(n => n + 1);
}}>Increase the number</button>
</>
)
}
https://codesandbox.io/p/sandbox/4zryt5?file=%2Fsrc%2FApp.js
- setNumber(number + 5) : number는 0이므로 setNumber(0 + 5)
React는 "5로 바꾸기" 를 큐에 추가한다. - setNumber(n => n + 1) : React는 업데이터 함수를 큐에 추가한다.
다음 렌더링하는 동안 React는 state 큐를 순회한다.
queued update | n | returns |
*5로 바꾸기* | 0 | 5 |
n => n + 1 | 5 | 5 + 1 = 6 |
React는 6을 최종 결과로 저장하고 useState에서 반환한다.
🖥️ 업데이트 후 state를 바꾸면 어떻게 되나요?
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
setNumber(n => n + 1);
setNumber(42);
}}>Increase the number</button>
</>
)
}
https://codesandbox.io/p/sandbox/2vd475?file=%2Fsrc%2FApp.js
- setNumber(number + 5) : number는 0이므로 setNumber(0 + 5)
React는 “5로 바꾸기” 를 큐에 추가한다. - setNumber(n => n + 1) : React는 업데이터 함수를 큐에 추가한다.
- setNumber(42): React는 “42로 바꾸기” 를 큐에 추가한다.
다음 렌더링하는 동안 React는 state 큐를 순회한다.
queued update | n | returns |
5로 바꾸기 | 0 | 5 |
n => n + 1 | 5 | 5 + 1 = 6 |
42로 바꾸기 | 6 | 42 |
React는 42를 최종 결과로 저장하고 useState에서 반환한다.
🔗 참고
'React' 카테고리의 다른 글
[React] useRef로 Tab 구현하기 (1) | 2024.12.04 |
---|---|
[React] 구글 로그인 구현하기 (1) | 2024.12.04 |
[React] lazy loading (2) | 2024.10.01 |
[React] React Hooks (0) | 2024.09.18 |
[React] Vite 사용하기 (1) | 2024.09.07 |