useState의 업데이트 방식은 크게 두가지가 있습니다.
함수형 업데이트
와 일반 업데이트
입니다.
일반 사용법과 함수형 업데이트 방식의 차이점이 무엇일까요? 두개의 코드를 비교해봅시다.
먼저 일반 업데이트 방식으로 onClick안에서 setNumber(number + 1) 를 3번 호출했습니다. number가 1씩 증가하는군요.
// src/App.js
import { useState } from "react";
const App = () => {
const [number, setNumber] = useState(0);
return (
<div>
{/* 버튼을 누르면 1씩 플러스된다. */}
<div>{number}</div>
<button
onClick={() => {
setNumber(number + 1); // 첫번째 줄
setNumber(number + 1); // 두번쨰 줄
setNumber(number + 1); // 세번째 줄
}}
>
버튼
</button>
</div>
);
}
export default App;
이렇게 동작하는 이유는 useState는 비동기적 처리를 하기 때문입니다.
비동기적 처리란, 어떤 작업을 처리하면서 다른 작업도 진행하는 것을 뜻합니다.
예를 들어, 카페에 갔는데 사장님 혼자 주문받고 일하면, 손님 한 명의 주문을 받고 음료를 제조하는 동안 다른 손님은 주문도 불가능하죠. 이것이 동기 처리입니다. 하지만 직원을 두어 주문 담당과 제조담당을 따로 둔다면 손님은 주문을 계속해서 할 수 있고, 그동안 제조담당은 음료를 계속해서 제조할 수 있습니다. 이것이 비동기 처리입니다.
setState는 리렌더링 될 때까지 값을 갱신하지 않습니다. 리액트가 효율적으로 렌더링하기 위해 여러 개의 상태 값 변경 요청을
batch(일괄 처리)
처리하기 때문입니다.
그렇기 때문에 number가 0인 상태에서 +1만 계속 해주고 있는 셈이죠.
batch 처리의 이유는 성능 이슈 때문입니다. 리렌더링을 발생하는 setState가 일어날 때마다 리렌더링이 일어난다면 엄청나게 많은 렌더링이 일어나겠죠.
incrementCount() {
// 주의: 이 코드는 예상대로 동작하지 *않을 것*입니다.
this.setState({count: this.state.count + 1});
}
handleSomething() {
// `this.state.count`가 0에서 시작한다고 해봅시다.
this.incrementCount();
this.incrementCount();
this.incrementCount();
// React가 컴포넌트를 리렌더링할 때 `this.state.count`는 3이 될 것 같은 예상과 달리 1이 됩니다.
// 이것은 `incrementCount()` 함수가 `this.state.count`에서 값을 읽어 오는데
// React는 컴포넌트가 리렌더링될 때까지 `this.state.count`를 갱신하지 않기 때문입니다.
// 그러므로 `incrementCount()`는 매번 `this.state.count`의 값을 0으로 읽은 뒤에 이 값을 1로 설정합니다.
}
이번에는 함수형 업데이트
방식으로 동일하게 작동시켜보겠습니다. number가 3씩 증가하네요.
// src/App.js
import { useState } from "react";
const App = () => {
const [number, setNumber] = useState(0);
return (
<div>
{/* 버튼을 누르면 3씩 플러스 된다. */}
<div>{number}</div>
<button
onClick={() => {
setNumber((previousState) => previousState + 1);
setNumber((previousState) => previousState + 1);
setNumber((previousState) => previousState + 1);
}}
>
버튼
</button>
</div>
);
}
export default App;
함수를 전달하게 되면 함수 안에서 이전 state값에 접근할 수 있고, 순차적으로 처리하기 때문에 동기적 처리
가 됩니다.
[React] useState의 비동기적 동작
컴포넌트 State
[ React ] useState 의 렌더링과 함수형 업데이트