공부/Error

onClick 이벤트 핸들러 2개 오류(setTimeout)

뀨뿌뀨뿌 2023. 7. 7. 20:26

❓ 오류 발생 상황과 이유

  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함수가 실행되게 만들어 주면 가능해짐