사이드 프로젝트를 진행하면서 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 의 계산을 통해 맨 처음인지, 맨 끝인지를 판단했다.
맨 처음

중간

맨끝

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