const singleObject = Object.assign({},
objectFromSetState1,
objectFromSetState2,
objectFromSetState3
);
이렇게 리액트는 모든 state의 변경을 한데 모아 배칭하여 리렌더링한다.
이 방법은 여러 state의 변경을 한번에 모아 처리하므로 성능이 좋지만 아래와 같은 상황에서 원하는 결과를 얻기가 힘들다. (모든 변경마다 리렌더링을 하면 성능에 문제가 생김)
import React, { useState } from "react"
function App() {
const [num, setNum] = useState(1)
async function plus() {
setNum(num + 1)
setNum(num + 1)
setNum(num + 1)
}
async function minus() {
setNum(num - 1)
}
return (
<div className="App">
<h1>{num}</h1>
<button onClick={plus}>PLUS</button>
<button onClick={minus}>MINUS</button>
</div>
);
}
export default App;
그 이유는 위에서 설명한 object composition에 있다. 위 세가지 변경을 한데 모아 처리하므로 결과는 한번 실행한 것과 같다.
문제가 되는 코드의 동작은 위와 같다. 한번에 처리하여 모두 처리 전 num값을 가지고 있어 1 + 1 의 결과만이 들어간 것이다.
그렇다면 위와 같이 최신의 state값을 참조하여
여러번의 변경을 수행해야하는 로직은 어떻게 작성해야할까?
바로 아래와 같이 함수형 업데이트를 사용하여 항상 최신값을 가져와 set을 해야한다.
import React, { useState } from "react"
function App() {
const [num, setNum] = useState(1)
async function plus() {
setNum(num => num + 1)
setNum(num => num + 1)
setNum(num => num + 1)
}
async function minus() {
setNum(num - 1)
}
return (
<div className="App">
<h1>{num}</h1>
<button onClick={plus}>PLUS</button>
<button onClick={minus}>MINUS</button>
</div>
);
}
export default App;
useState의 내부 로직은 아래와 같다
// React Hooks
// ----------------------------------------------------------------------
// based on the code in https://github.com/facebook/react/pull/13968
// Unlike the class component setState, the updates are not allowed to be partial
type SetStateAction<S> = S | ((prevState: S) => S);