✅ 동일한 setState 함수를 ”setState(value) 형태로” 여러번 호출한다면?
- 맨 마지막 업데이트된 state로만 반영됨.
- value = 6 , 12 , 18… 이 아닌, 3, 6, 9가 됨.
const InputPrac = () => {
const [value, setValue] = useState(0); // value = 3 6 9 ...
const addNum = (e) => {
setValue(value + 1);
setValue(value + 2);
setValue(value + 3);
};
return (
<>
<p>{value}</p>
<button onClick={addNum}>클릭</button>
</>
);
};
export default InputPrac;
설명
리액트는 setState가 호출되면 state가 변경되는 것으로 인지하는데,
한번의 이벤트 발생시 연속으로 같은 setstate가 실행되면,state가 업데이트되어 연속으로 리렌더링 될 것이다.
이는 비효율적이고 비용도 많이 든다.
때문에 이벤트 발생시 실행되는 콜백함수 내에서의 state의 "가장 마지막 갱신 내용"으로 state를 "한번만" 업데이트 시키게 된다.
✅ 동일한 setstate함수를 “콜백함수 형식으로” 여러번 호출한다면?
위의 내용과 달리 , setstate함수를 "호출할 때 마다" state가 연속으로 갱신되고, 그 값을 인자로 받아서 사용할 수 있다.
이 방식을 통해 갱신된 state값을 사용할 수 있다.
const InputPrac = () => {
const [value, setValue] = useState(0); // value = 6 12 18 ...
const addNum = (e) => {
setValue((prev) => prev + 1); // prev = 0 // updated value = 1
setValue((prev) => prev + 2); // prev = 1 // updated value = 3
setValue((prev) => prev + 3); // prev = 3 // updated value = 6
};
return (
<>
<p>{value}</p>
<button onClick={addNum}>클릭</button>
</>
);
};
설명
- setstate를 콜백함수 형식으로 쓴다면, setstate의 인자로 업데이트 된 state값을 받아올 수 있다.
- 하지만 setstate함수를 통해 갱신된 state가 DOM에 리렌더 되는 때는
addNum 콜백함수 본문이 다 끝나고 나서 반영되기 때문에, 최종 업데이트된 값(6, 12 , 18으로 보여지게 되는 것이다.
✅ 결론 - useState 의 setState는 비동기적으로 동작한다
<문제의 코드>
const InputPrac = () => {
const [value, setValue] = useState(0);
// value : 0 , 6 , 12 , 18
const [valueMul, setValueMul] = useState(100);
// valueMul : 100(value = 0) , 106(value = 6) , 118(value = 12)
const addNum = (e) => {
setValue((prev) => prev + 1); // 1
setValue((prev) => prev + 2); // 3
setValue((prev) => prev + 3); // 6, 12, 18
setValueMul((prev) => value + prev); // 100(value = 0) 106(value = 6) 118(value = 12)
};
return (
<>
<p>{value}</p>
<p>value가 바로 반영이 안됨 => {valueMul}</p>
<button onClick={addNum}>클릭</button>
</>
);
};
문제
- setValue가 최종적으로 6으로 업데이트 되니까 그 값을 활용하여 setValueMul함수를 실행하려고 했음.
- 그러나 valueMul(100) + value(6) = 106을 기대했는데, 100이 나오고, 다음번 addNum실행시 value(6)이 참조되어 106이 나옴. 이런식으로 하나씩 밀려서 나옴.
이유 - 클로져의 원리 때문에
- setValueMul 함수가 실행될 땐, InputPrac함수의 스코프가 이미 끝나있다.
- 때문에 setValueMul함수 안에서 받는 prev인자는 InputPrac함수의 스코프가 있을당시의 값인 0을 참조하게 되는것이다. (클로져)
참조자료
1. https://stackoverflow.com/questions/42038590/when-to-use-react-setstate-callback\
'프론트엔드 > React' 카테고리의 다른 글
Controlled vs Uncontrolled (input요소 value와 defaultValue 차이) (1) | 2025.02.16 |
---|---|
Custom React 구현하기 (2) | 2024.12.22 |
useMemo, useCallback에 대해 (0) | 2023.12.10 |
[TIL] React router6 (0) | 2023.09.17 |
[TIL] Style-component (0) | 2023.09.17 |