❓ 오류 발생 상황과 이유
const { color, reverseColor, size, comment, icon } = props
const [isClicked, setIsClicked] = useState(false);
const onReverseColor = () => {
setIsClicked(true);
setTimeout(() => {
setIsClicked(false);
}, 250);
};
const onOpenAlert = () => {
if (comment === "Large Primary Button") {
window.alert("버튼을 만들어보세요");
}
if (comment === "Large Negative Button") {
window.prompt("어렵나요?");
}
};
return (
<MainButton
color={color}
reverseColor={reverseColor}
onClick={() => {
onReverseColor();
onOpenAlert();
}}
isClicked={isClicked}
size={size}
>
- onReverseColor와 const onOpenAlert가 동시에 실행되어야 하는 버튼에서 오류가 발생
=> onOpenAlert만 실행되고 onReverseColor실행되지 않음
- 리액트 컴포넌트는 이벤트 핸드러나 라이프 사이클 메소드 내에서 여러 개의 상태 업데이트가 한 번에 그룹화되어 적용되는 배치 업데이트 매커니즘을 가지고 있음
=> 이 최적화로 다시 렌더링되는 횟수를 줄여 성능을 향상시켜줌
- 위에 코드를 보면 onReverseColor함수는 setIsClicked(true)로 상태를 업데이트 시키고 250ms 지연시킨 후 setIsClicked(false) 을 수행하는 setTimeout 함수가 실행됨
onOpenAlert함수는 MainButton 컴포넌트의 onclick 이벤트 핸드러 내에서 onReverseColor 다음에 즉시 호츨되는데 setTimeout 의 비동기적인 특성으로 인해 onOpenAlert함수가 setTimeout 함수가 실행되고 setIsClicked(fasle)을 설정하기 전에 호출될 수 있어서 onReverseColor가 실행되지 않는 것처럼 보일 수 있음
⭐해결방법
const { color, reverseColor, size, comment, icon } = props;
const [isClicked, setIsClicked] = useState(false);
const onReverseColor = () => {
setIsClicked(true);
setTimeout(() => {
setIsClicked(false);
onOpenAlert();
}, 250);
};
const onOpenAlert = () => {
if (comment === "Large Primary Button") {
window.alert("버튼을 만들어보세요");
}
if (comment === "Large Negative Button") {
window.prompt("어렵나요?");
}
};
return (
<MainButton
color={color}
reverseColor={reverseColor}
onClick={onReverseColor}
isClicked={isClicked}
size={size}
>
- setTimeout함수내에서 setIsClicked 상태 업데이트 후 onOpenAlert함수가 실행되게 만들어 주면 가능해짐