이챙의 개발 log
useState는 비동기적으로 동작한다!
useState(setState)를 사용할때 그런경우가 있다. 바로 엇,,왜 내가 생각한대로 동작이 안되지,,?
그 이유는 바로 비동기적으로 동작하기 때문이었다.
useState가 비동기적으로 동작하는 이유에 대해서 알아보려고 한다.
원인을 알아보기
function App() {
const [number, setNumber] = useState(1);
const handleAdd = () => {
setNumber(number + 1);
};
const handleMultiply = () => {
setNumber(number * 2);
};
const handleMultiplyAddNumber = () => {
setNumber(number * 2);
setNumber(number + 1);
};
return (
<>
<button onClick={handleAdd}>+ 1</button>
<button onClick={handleMultiply}>* 2</button>
<button onClick={handleMultiplyAddNumber}>* 2 + 1</button>
<p style={{ color: '#fff' }}>{number}</p>
</>
);
}
number의 초기값 1 부터 시작하면
1. +1 클릭 -> 2
2. +1 클릭 -> 3
3. +1 클릭 -> 4
4. *2 클릭 -> 8
5. *2 + 1 클릭 -> 9
6. *2 + 1 클릭 -> 10
7. *2 + 1 클릭 -> 11
요 순서로 number의 값이 증가되고 있다. 하지만 5번부터 뭔가 이상하다. 😟
값이 17이 되야 하는데 9가 됬다. 즉 *2는 건너뛰고 +1만 계산이 되고 있는 것이다.
const handleMultiplyAddNumber = () => {
setNumber(number * 2);
setNumber(number + 1);
};
문제의 함수다.
setState는 여러번 호출되고 있다. 이때 리액트는 성능을 위해서 setState를 한꺼번에 처리한다. 즉 setNumber(number * 2) 를 처리하고 그다음에 setNumber(number + 1)를 계산하는 방식으로 동기적으로 하지 않고 단일 업데이트로 한꺼번에 처리한다는 것이다.
State 업데이트는 병합된다.
Object.assign(
{number},
{number : number + 1},
{number : number * 2},
...
)
setState를 여러번 호출하게 되면 Object.assign처럼 일괄적으로 병합되어 업데이트 되는 것이다.
위의 코드를 계산해보면 이전의 number값을 참조하는것이 아니라 현재 number의 값을 참조하게 되서 마지막의 계산 값인 2가 나오게 된다.
setState도 여러번 호출하게 되면 위와같이 동작 하므로 handleMultiplyAddNumber의 값이 1만 더해진 결과가 나오게 된것이다.
그렇다면 비동기를 해결할 방법은?
setState에서 이전의 값을 참조하도록 인자와 함께 함수를 전달하는 방법이 있다.
const handleMultiplyAddNumber = () => {
setNumber(prevNumber => prevNumber * 2);
setNumber(prevNumber => prevNumber + 1);
};
이전의 state값을 참조하게 되므로 최신 state의 값을 유지하게 될 수 있다.
'react' 카테고리의 다른 글
리액트로 마우스 드래그 가로 스크롤 구현하기 (+합성 컴포넌트로 재사용 높이기) (1) | 2024.09.19 |
---|---|
리액트로 리뷰 별점(Rating) 구현하기(소수점,클릭했을때) (0) | 2024.07.26 |
framer-motion으로 리액트에서 애니메이션을 쉽게 ✨ (0) | 2024.04.19 |
useTransition으로 성능 개선하기 (0) | 2024.02.28 |
react+webpack+tailwindcss 설치하기! (0) | 2022.09.19 |
이챙(leechaeng)
프론트엔드 개발도 하고 뛰기도 하고