React Carousel 만들기

Soondol·2024년 2월 13일

사이드 프로젝트를 진행하면서 Carousel기능을 구현해야했다.

React-swiper, react-slick 등 아주 좋은 라이브러리들은 많지만

위의 사진처럼 pagenation의 위치, css등의 커스텀이 필요해
직접 구현하기로했다.

각각의 카드를 컴포넌트로 먼저 작성해주고

const CommonCard = ({ url }: ICard) => {
  return (
    <div >
        <Image className="이미지 css" src={이미지URL} alt="" />
    </div>
  );
};

카드들을 뿌려 이미지들이 나열될 컴포넌트를 작성해준다.

interface SliderProps {
  slideData: ICard[];
  currentIndex: number;
  nextSlide: () => void;
  prevSlide: () => void;
}

const Slider = ({
  slideData,
  currentIndex,
  nextSlide,
  prevSlide,
}: SliderProps) => {
  const slideData = [.....];
  
  return (
    <div>
      <div className="flex gap-10">
        {slideData.map((item, index) => (
          <div
            key={index}
            className={`
              ${
                index >= currentIndex && index < currentIndex + 4
                  ? ''
                  : 'hidden'
              }
            `}
          >
            <CommonCard url={item.url} />
          </div>
        ))}
      </div>
    </div>
  );
};

index >= currentIndex && index < currentIndex + 4 ? '' : 'hidden'

이부분을 통해 map의 index와 현재 이미지 순서+4 까지만 요소를 나타내주었고,

이후 Carousel을 사용할 곳에

const [currentIndex, setCurrentIndex] = useState(0);
  const nextSlide = () => {
    setCurrentIndex((prevIndex) =>
      prevIndex === slideData.length - 1 ? 0 : prevIndex + 1,
    );
  };

  const prevSlide = () => {
    setCurrentIndex((prevIndex) =>
      prevIndex === 0 ? slideData.length - 1 : prevIndex - 1,
    );
  };
  
  ....
  
<div className="flex items-center gap-x-1 text-primary-500">
          <button
            className={` ${
              currentIndex === 0 ? 'opacity-50 cursor-default' : ''
            } rounded-full bg-primary-500 bg-opacity-20 p-2 hover:bg-opacity-70`}
            onClick={prevSlide}
            disabled={currentIndex === 0}
          >
            <FaChevronLeft />
          </button>
          <button
            className={`${
              currentIndex === slideData.length - 4
                ? 'opacity-50 cursor-default'
                : ''
            } rounded-full bg-primary-500 bg-opacity-20 p-2 hover:bg-opacity-70`}
            onClick={nextSlide}
            disabled={currentIndex === slideData.length - 4}
          >
            <FaChevronRight />
          </button>
</div>
          ....
          
<div className="flex gap-10 pt-20">
          <Slider
            slideData={slideData}
            currentIndex={currentIndex}
            nextSlide={nextSlide}
            prevSlide={prevSlide}
          />
</div>

나타낼 이미지들의 갯수를 체크해 첫번째이거나 마지막 이미지일때
< , > 각 버튼들을 비활성화 시켜줬다.

나는 4개씩 이미지를 나타내고있기에
slideData.length - 4 의 계산을 통해 맨 처음인지, 맨 끝인지를 판단했다.

맨 처음

중간

맨끝

급하게 찾아보고 구현해보느라 조금 복잡한감이 없지않아있다.
아마 사이드프로젝트 진행하면서 분명히 또 쓰일텐데
더 나은방법을 구상해보고 마우스이벤트 등을 추가해봐야겠다.


0개의 댓글