React Carousel 구현하기

김현조·2023년 4월 5일
8

FrontEnd

목록 보기
6/9
post-thumbnail

캐러셀 직접 구현하기

react-material-ui-carousel 라이브러리를 사용해 넣어놓았던 메인페이지, 문제 목록 페이지의 캐러셀을 직접 구현하기로 했다. 이유는 다음과 같다.

  1. 번들사이즈 감소
  2. 첫 로딩시에 캐러셀 내용이 퍼지듯이 렌더링되었는데 이게 버그로 보이는 문제 발생
  3. 슬라이드 애니메이션 커스텀

번들 포비아

번들 포비아에서 분석한 package.json 번들 사이즈 내림차순 정렬 결과 2위인 react-material-ui-carousel

결과물

캐러셀

이슈

애니메이션

슬라이드 애니메이션을 넣으니 마지막 idx -> 첫번째 idx로 이동할 때 이어지는 것처럼 보이지 않았다. 한번에 x축이 + 100%씩 이동하다가 갑자기 -200% 이동했기 때문이다.
-> 눈속임으로 마지막에 첫번째 내용과 동일한 슬라이드를 하나 추가하고, 마지막 슬라이드로 넘어가면 잠깐 transition을 멈춰놓고 몰래 첫번째 슬라이드로 바꿔치기한 후 다시 transition을 넣어주는 방식으로 해결 가능.

아래와 같이 현재 슬라이드 인덱스, transition 들어갔는지 여부 두가지 상태를 가지고 구현해볼 수 있다.

  const [currIdx, setCurrIdx] = useState(1);
  const [transition, setTransition] = useState(true);

다음 슬라이드로 넘어갈때 setCurrIdx를 호출해 인덱스를 설정해준다. 범위를 넘어갔을 때의 예외처리와 함께 앞서 언급한 transition on/off 로직을 구현하면 된다. 여기서 replaceSlide가 해당 로직인데 아래에 분리해놓았다.

  const moveSlide = (offset: number) => {
    let nextIdx = currIdx + offset;
    setCurrIdx(nextIdx);
    if (nextIdx <= 0) {
      nextIdx = items.current.length - 1;
      replaceSlide(nextIdx);
    } else if (nextIdx >= items.current.length - 1) {
      nextIdx = 0;
      replaceSlide(nextIdx);
    }
    setTransition(true);
  };

일단 슬라이드를 옮기고 나서 실제로 바꾸고자 하는 위치로 몰래 바꿔치기 하겠다는 뜻. (ex. 마지막 슬라이드에 도착했다면 0번으로 바꾸겠다.)

  const replaceSlide = (idx: number) => {
    setTimeout(() => {
      setCurrIdx(idx);
      setTransition(false);
    }, 700);
  };

자동으로 넘기기 (Interval)

react에서는 state가 바뀌면 앱도 리렌더링이 되기 때문에 setInterval이 무한루프에 빠지게 된다. 이것을 해결하기 위해 Dan Abramov님의 해결책을 읽어볼 수 있으며 결론은 다음과 같은 custom hook이다.

import { useState, useEffect, useRef } from 'react';

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

이는 callback 데이터가 바뀔 때마다 useEffect()가 실행되어 savedCallback의 current 값이 새로운 callback 데이터로 업데이트되도록 구현된 hook이다.

이렇게 직접 Carousel을 구현해볼 수 있다.

0개의 댓글