I am using swiper.js/react, I had to create a carousal having next and prev buttons to move single slide, also need to add buttons to move the pages by the given breakpoints in the code (in accordance with slidesPerView).
next and prev buttons work perfectly but the Dots / Page buttons not working properly when carousal has looped & slidesPerView, slideToLoop sometimes move only one slide (this is the main issue), even if added a static value to move to slideToLoop 0.
Please find the code below
import { Swiper, SwiperSlide } from "swiper/react";
import ArtistCard from "../songcards/artistcard";
import { useEffect, useRef, useState } from "react";
import { NextSvg, PrevSvg } from "../../assets/svg";
const Dots = ({ swiperRef, slideLength }) => {
const [index, setIndex] = useState(0);
const [pageLength, setPageLength] = useState(0);
const changeSlide = (index) => {
const newIndex = Math.floor(
(swiperRef.current.slides.length / pageLength) * index
);
swiperRef.current?.slideToLoop(newIndex);
};
useEffect(() => {
const swiperEle = swiperRef.current;
const handleChange = () => {
const curr_index = swiperEle.realIndex;
const per_page = Math.floor(slideLength / pageLength);
setIndex(Math.floor(curr_index / per_page));
};
if (swiperEle) swiperEle.on("slideChange", handleChange);
return () => {
if (swiperEle) swiperEle.off("slideChange", handleChange);
};
}, [swiperRef, pageLength, slideLength]);
useEffect(() => {
const updateSlidesPerView = () => {
const width = window.innerWidth;
if (width >= 1024) {
setPageLength(slideLength / 6);
} else if (width >= 768) {
setPageLength(slideLength / 4);
} else if (width >= 640) {
setPageLength(slideLength / 3);
} else {
setPageLength(slideLength / 2);
}
};
updateSlidesPerView();
window.addEventListener("resize", updateSlidesPerView);
return () => {
window.removeEventListener("resize", updateSlidesPerView);
};
}, [slideLength]);
if (pageLength)
return (
<>
{Array.from({ length: pageLength }).map((_, dotIndex) => (
<span
key={dotIndex}
className={`${dotIndex} cursor-pointer h-[4px] inline-block rounded-sm transition-all duration-300 ${
dotIndex === index ? "w-5 bg-white" : "w-[10px] bg-[#c0c0c0]"
} ${dotIndex === pageLength - 1 ? "" : "mr-[10px]"}`}
onClick={() => changeSlide(dotIndex)}
></span>
))}
</>
);
};
const HeroArtistsCarousal = () => {
const swiperRef = useRef(null);
const handleNext = () => swiperRef.current && swiperRef.current.slideNext();
const handlePrev = () => swiperRef.current && swiperRef.current.slidePrev();
const artists = [...];
return (
<div className="relative">
<Swiper
spaceBetween={30}
slidesPerView={2}
loop={true}
breakpoints={{
640: {
slidesPerView: 3,
},
768: {
slidesPerView: 4,
},
1024: {
slidesPerView: 6,
},
}}
onSwiper={(swiperInstance) => {
swiperRef.current = swiperInstance;
}}
>
{artists.map((artist) => (
<SwiperSlide key={artist.id}>
<ArtistCard artist={artist} />
</SwiperSlide>
))}
</Swiper>
<div className="mt-7 flex justify-end items-center">
<Dots swiperRef={swiperRef} slideLength={artists.length} />
<button
onClick={handlePrev}
className="hidden 2lg:inline-block ml-[10px]"
>
<PrevSvg className="fill-white hover:fill-[#25a56a] w-[30px] h-[30px] transition-colors duration-300" />
</button>
<button onClick={handleNext} className="hidden 2lg:inline-block">
<NextSvg className="fill-white hover:fill-[#25a56a] w-[30px] h-[30px] transition-colors duration-300" />
</button>
</div>
</div>
);
};
export default HeroArtistsCarousal;
Any help would be appreciated!