React 에서 상태(state) 를 업데이트 할 때 setCounter(count + 1); 로 상태를 업데이트 할 수 있지만,
setCounter((current) => current + 1); 처럼 함수형 업데이트를 사용하는 것을 더 권장한다.
왜냐하면 이 방식이 더 상태를 업데이트할 때 안전한 방식이기 때문이다.
setCounter(counter + 1); 보다 setCounter((current) => current + 1); 이 더 안전한 이유는
React 의 상태 업데이트 방식 때문이다.
1. 비동기적인 상태 업데이트
React에서 useState의 setState 함수는 비동기적으로 실행된다.
즉, 여러 개의 setCounter 호출이 있을 때, 예상과 다르게 이전 값이 덮어 씌워질 가능성이 있다.
const [counter, setCounter] = useSatate(0);
const handleClick = () => {
setCounter(counter + 1);
setCounter(counter + 1);
setCounter(counter + 1);
}
이 코드를 실행하면, counter 가 1씩 증가하는 것이 아니라, 한 번의 클릭으로 1만 증가할 수 있다.
그 이유는 counter 값이 상태 업데이트 전에 고정되기 때문이다.
예상
- counter 가 0에서 시작했으니, handleClick() 을 실행하면 counter + 1 이 세 번 실행되어 3이 될 것 같음.
실제 동작
- React에서는 상태 업데이트가 비동기적으로 처리됨.
- 즉, 첫 번째 setCounter(counter + 1);을 실행해도 counter의 값은 0으로 유지될 수 있다.
- 첫 번째 setCounter(counter + 1); → counter 는 0이므로, 0 +1 = 1
- 두 번째 setCounter(counter + 1); → counter 는 여전히 0(이전 업데이트가 반영되지 않았으므로), 0 + 1 = 1
- 세 번째 setCounter(counter + 1); → 동일하게 1
- 결국, counter 의 최종 값은 1이 됨.
🤔 그렇다면 상태 업데이트는 언제 이루어질까?
상태 업데이트 함수는 함수 호출이 끝난 후 비동기적으로 실행된다.
React는 여러개의 setState 호출을 일괄처리(batch update) 하면서 성능을 최적화하기 때문에,
함수가 실행되는 동안은 상태가 즉시 변경되지 않고, 여전히 이전 값을 유지한다.
따라서 이전 이전 값을 기반으로 업데이트하면 문제가 발생하는 것이다.
🤔 ‘상태 업데이트가 비동기적이다.’란?
setState를 호출한 순간에 즉시 상태가 바뀌지 않고, React가 일정한 타이밍에 여러 개의 setState를 모아서(batch 처리) 한 번에 업데이트한다는 뜻
즉, setState 를 실행 했다고 해서 그 다음 줄에서 바로 변경된 상태를 사용할 수 없다는 것이 핵심.
따라서 함수 실행 중에는 이전 상태 값이 그대로 유지되고, 함수가 끝난 뒤에 React가 상태 변경을 반영하고 컴포넌트를 리렌더링하는 구조임.
2. 업데이트 함수 방식이 안전한 이유
setCounter((current) => current + 1);
setCounter((current) => current + 1);
setCounter((current) => current + 1);
위 코드에서 setCounter 에 업데이트 함수를 전달하고 있다.
React는 이전 상태 값(current)을 안전하게 가져와서 업데이트 하므로, 여러 번 호출해도 정상적으로 3이 증가하게 된다.
3. 결론
- setCounter(counter + 1); 은 현재 counter 의 값이 변하지 않은 상태에서 덮어 씌워질 가능성이 있다.
- setCounter((current) => current + 1); 은 React 가 최신 상태 값을 안전하게 보장해준다.
따라서, 이전 상태를 기반으로 값을 업데이트할 때는 업데이트 함수를 사용하는 방식이 더 안전하다.
다음으로 쓰고 싶은 글의 주제들
1️⃣ Javascript 의 실행 컨텍스트와 클로저
- setState가 비동기적으로 동작하면서 함수 실행이 끝날 때까지 상태가 변경되지 않는 이유를 이해하려면, Javascript 의 실행 컨텐스트(Execution Context)와 클로저(Closure) 개념이 중요함.
- 함수 내부에서 count 변수는 함수가 실행되는 순간의 값(클로저에 저장된 값)을 참조하기 때문에, setState를 여러 번 호출해도 동일한 값이 사용될 수 있음.
2️⃣ JavaScript의 비동기 처리(이벤트 루프, 태스크 큐)
3️⃣ React의 상태 관리(useState)와 리렌더링 흐름
'👨💻 FrontEnd > 🔵 리액트 [React]' 카테고리의 다른 글
[ react ] 로컬스토리지 활용 : 사용자 아이디 기억하기(remember ID) (0) | 2024.06.05 |
---|---|
[ React ] 공식문서 읽고 틱택톡 예제 따라해보기 (0) | 2024.05.29 |
[React] 리액트 공식문서 보고 useState, component 이해하기 (0) | 2024.05.28 |