본문 바로가기

공부기록/[강의노트] Udemy React 완벽가이드 101~200

# 157 [udemy React 완벽 가이드 노트] 장바구니에 item의 수량이 변경될 때마다 애니메이션 발동시키기

버튼에 범프 효과를 주고 크기를 변경해주는 애니메이션을 구현한 

CSS코드를 준비한다. 

 

button에 그 클래스를 추가하도록 하자. 


 

 const btnClasses = `${classes.button} ${classes.bump}`;
return (
    <button className={btnClasses} onClick={onClickOpen}>

 

 

새로고침 하면 처음 한 번 해당 애니메이션을 볼 수 있다. 

 

 

 

 

 

장바구니의 amount가 변경될 때마다 애니메이션을 실행해보자.


 useEffect를 사용하면 될 것이다. 

 

 

목표  :

 

bump 클래스를 포함하는 클래스명으로 바꿨다가 

타이머를 설정해 bump클래스를 삭제했다가 

다시 장바구니에 item이 변경되면 다시 bump 클래스를 

추가해보자.

 

 

state를 관리하여 컴포넌트를 재평가 하고 

렌더링을 다시 할 수 있도록

useState를 import하고 useState를 각각 할당하자. 

const [btnIsHighlighted, setBtnIsHighlighted] = useState(false);

 

그리고 useEffect에 setState를 실행하자.

 useEffect(() => {
    setBtnIsHighlighted(true);

 

 

그리고 btnIsHighlighted일 때만 bump 클래스가 추가되도록 하자.

 

const btnClasses = `${classes.button} ${
    btnIsHighlighted ? classes.bump : ""
  }`;

 

 

그러면 실제 실행 결과는, 

useEffect안에서 state를 업데이트 해서 

state가 변경되면 

전체 컴포넌트가 다시 실행 된다. 

 

그러면 btnClasses코드가 변경되고 

업데이트 된 클래스가 button에서 선택되는 것이다.

 

그런데 계속 바뀌면 안된다. 

 

1. 장바구니에 item의 수량이 0보다 클 경우에만 실행된다

(수량이 0일경우 return)

 useEffect(() => {
    if (cartCtx.items.length === 0) return;
    setBtnIsHighlighted(true);

 

2. dependencies를 추가해보자. 

cartCtx를 추가하면 전체 cartCtx가 바뀔 때마다 실행되므로 안된다. 

cartCtx.items가 바뀌었을 때만 실행되도록 해보자. 

 

const { items } = cartCtx;
useEffect(() => {
    if (items.length === 0) return;
    setBtnIsHighlighted(true);
  }, [items]);

그러면 장바구니에 무언가 담겼을 첫 번째만 실행이 된다. 

왜그럴까? 

 

클래스가 한번 추가된 이후 삭제되지 않았기 때문이다.

 

 

 

3. timer를 통해 btnIsHightlighted를 false로 다시 변경해 주자.

 

useEffect(() => {
    if (items.length === 0) return;
    setBtnIsHighlighted(true);

    setTimeout(() => {
      setBtnIsHighlighted(false);
    }, 30);
  }, [items]);

 

4. clearTimeout을 작성해주자. 

컴포넌트가 삭제될 때 timeout을 지워주는 함수를 

작성해주어야 한다. 지금은 컴포넌트가 삭제되지는 않지만, 

 

타이머 또는 실행 중일 수도 있는 기타 사이드 이펙트들은 

정리하는게 좋은 습관이다. 

 

useEffect(() => {
    if (items.length === 0) return;
    setBtnIsHighlighted(true);

    const timer = setTimeout(() => {
      setBtnIsHighlighted(false);
    }, 30);

    return () => {
      clearTimeout(timer);
    };
  }, [items]);