블로그 리팩토링 트러블 슈팅

Changmok LEE·2025년 8월 3일
  • 트러블 슈팅

    supabase로 데이터를 불러 오고 화면이 커버플로우 display가 되어야 하는데 안됨
const CoverflowSection = () => {
  const captionDatas = useCaptionDatas();
  const { coverflowSectionRef, captionsRef } = useCoverflowRefs();
  useDisplayCaptions({ captionsRef });
  useCoverflowScroll({ coverflowSectionRef, captionsRef });

  return (
    <CoverflowSectionWrapper ref={coverflowSectionRef}>
      {captionDatas?.map((caption, i) => (
        <CoverflowCaption
          key={caption.id}
          ref={(captionElem: HTMLDivElement) => {
            captionsRef.current[i] = captionElem;
          }}
          data={caption}
          onClick={() => handleCaptionClick(i, { coverflowSectionRef, captionsRef })}
          index={i}
        />
      ))}
      <Placehorder />
    </CoverflowSectionWrapper>
  );
};

export default CoverflowSection;

useDisplayCaptions 훅에 captionDatas 업데이트가 감지되지 않아 렌더링 초기 1회만 display 되고 captionDatas가 업데이트 되는 경우는 고려되지 않음

const useDisplayCaptions = ({ captionsRef }: useDisplayCaptionsProps) => {
  useEffect(() => {
    displayCaptions({ captionsRef, selectedIndex: 0, scrollLeft: 0 });
  }, [captionsRef]);
};

export default useDisplayCaptions;

해결책: captionDatas를 prop으로 전달해 useEffect에 의존성 추가

const useDisplayCaptions = ({ captionsRef, captionDatas }: useDisplayCaptionsProps) => {
  useEffect(() => {
    displayCaptions({ captionsRef, selectedIndex: 0, scrollLeft: 0 });
  }, [captionsRef, captionDatas]);
};

export default useDisplayCaptions;

왜 이런 문제가 발생했을까? supabase 도입 전에는 mockdata를 활용해 api 통신이 필요 없었기에 초기 1회만 랜더링 해주면 동작했지만 아래 코드와 같이 captionDatas의 초기 값은 null이므로 useDisplayCaptions 내 useEffect에 의존성 주입이 필요해짐

const useCaptionDatas = () => {
  const [captionDatas, setCaptionDatas] = useState<CaptionData[] | null>();

  useEffect(() => {
    const fetchCaptions = async () => {
      const { data, error } = await supabase.from('captionDatas').select('*');
      console.log(data);
      setCaptionDatas(data);
      if (error) {
        console.log(error);
      }
    };
    fetchCaptions();
  }, []);

  return captionDatas;
};

export default useCaptionDatas;

최종 결과

profile
이창목

0개의 댓글