[TIL] 0326

yoon Y·2022년 3월 27일
0

2022 - TIL

목록 보기
63/109

WaffleCard Refactoring

CardList Animation

문제점
스크롤이 끝나면 useInterval을 중단 시키는 코드를 useInterval의 콜백함수 안에 작성해줬다.
문제점은 delay초마다 스크롤이 끝난지 확인하는 로직이 실행되어 비효율적이다.

// WaffleCardList.tsx
useInterval(
   () => {
     if (!(targetDom instanceof Element)) return;

     const { scrollLeft, clientWidth } = targetDom;
     const currentScrolledWidth = Math.ceil(scrollLeft + clientWidth);
     const isRenderedCards = currentScrolledWidth > targetDom.clientWidth;
     const isFinishScroll = currentScrolledWidth === targetDom.scrollWidth;
     isRenderedCards && isFinishScroll && setIsPlayMove(false); 
     targetDom.scrollLeft += 1;
   },
   15,
   isPlayMove,
 );

해결책
intersection observer를 도입하여, 마지막 카드를 감시 target으로 걸어준다.
마지막 카드가 전부 보여질 때 useInterval을 중단시키는 콜백함수를 실행시키는 방법이다.

하지만 마지막 카드에 ref를 걸어주려면 forwardRef를 사용해야하는데 코드가 복잡해질 것 같아서
카드리스트에 새로운 div태그를 추가해줬다.

tab이 변경될 때마다 카드리스트와 div가 다시 렌더링되기 때문에
callback ref를 이용해 div가 새로 생성 될 때마다 Element가 target에 자동으로 할당되도록 했다.
하지만 새로 생성되는건 가상돔이고, 변경된 부분이 없기 때문에 돔은 새로 생성되지 않았다.
그래서 content로 type을 주어 tab이 바뀔 때마다 변경 부분이 생기도록 했다.

// useScrollAnimation.ts
  const [target, setTarget] = useState<HTMLDivElement | null>(null);

  const onIntersect: IntersectionObserverCallback = ([entry]) => {
    if (entry.isIntersecting) {
      setIsPlayMove(false);
    }
  };

  useEffect(() => {
    let observer: IntersectionObserver;
    if (target) {
      observer = new IntersectionObserver(onIntersect, {
        threshold: 0.1,
      });
      observer.observe(target);
    }
    return () => observer && observer.disconnect();
  }, [target]);

// WaffleCardList.tsx
...  
const [
    isPlayMove,
    setIsPlayMove,
    moveScrollToFront,
    moveScrollToBack,
    setTarget,
  ] = useScrollAnimation(cardsListRef.current, [type]);         


return (
          <>
           {waffleCards?.map(waffleCard => (
              <StyledWaffleCard
               type={type === 'my' ? 'my' : 'basic'}
               key={waffleCard.id}
               waffleCardData={waffleCard}
               onClickWaffleCard={handleClickWaffleCard}
               onClickLikeToggle={handleClickLikeToggle}
               onClickEdit={handleClickWaffleCardEdit}
               onClickDelete={handleClickWaffleCardDelete}
               />
               ))}
              <div ref={setTarget}>{type}</div> // 여기
           </>
          );
profile
#프론트엔드

0개의 댓글