purpose : 버튼을 클릭하면 이벤트에서 주는 값을 받아오고, 받아온 값을 state에 저장 후 if문 조건으로 해당 state 값이 있으면, api을 호출하고 싶었다.
issue : setState는 비동기로 처리한다. 그렇기에 setState로 변경했다고 해서 state값이 바뀌질 않는다.
그렇기에 if문을 만족하지 못해 api을 호출하지 않는 문제가 있었다.
resolution : 리액트에서 useState로 만든 변수의 값이 setState로 값을 변경 시키면 리렌더링이 발생한다.
setState로 천 번 값을 수정하면 천 번이나 리렌더링이 이루어질까 라고 했을 때 실제로는 그렇지 않다.
const [num, setNum] = useState(0);
const thousands = () => {
for (let i =0; i <= 10000; i++) {
setNum(i);
}
}
return (
<button onClick={thousands} >
천 번이나 랜더링이 될까?
</button>
<p>{num}</p>
)
위 코드를 실행시키면 숫자가 1부터 올라가질 않고 바로 10000을 보여준다.
만번을 리렌더링하는 것은 웃긴 일이다. 성능 측면에서도 일괄적으로 한번에 업데이트 되는 것이 더 좋다. 그렇기에 setState에 새로운 값을 큐에 넣은 후 일괄적으로 업데이트를 해준다. 그래서 위의 코드를 실행시키면 한 번에 10000으로 변하는 것 확인 할 수 있다. 그래서 setState는 비동기이며 setState후 바로 해당 state를 console.log로 확인해도 값이 업데이트 안될 것을 확인 할 수 있다.
그렇다면 어떻게 if문을 통과시킬 수 있을까?
useEffect를 사용한다.
const [num, setNum] = useState(0);
useEffect(() => {
if (num > 0) {
api 호출하기
}
}, [num])