I have a carousel armed with embla that at the time of the first load of my site does not show me the navigation arrows (left and right) and the dots at the bottom (it only shows me one, not as many as it should because of the number of images). When reloading everything is displayed correctly
I don't know if it's a problem with how the images are loaded, which is done correctly because by moving with the mouse I can navigate the carousel.
export const CarouselPropiedad = () => {
const [emblaRef, emblaApi] = useEmblaCarousel();
const [canNext, setCanNext] = useState(false); // Cambiado a false inicialmente
const [canPrev, setCanPrev] = useState(false);
const [selectedIndex, setSelectedIndex] = useState(0);
const [scrollSnaps, setScrollSnaps] = useState([]);
const [images, setImages] = useState([]);
const scrollPrev = useCallback(() => {
if (emblaApi) emblaApi.scrollPrev();
}, [emblaApi]);
const scrollNext = useCallback(() => {
if (emblaApi) emblaApi.scrollNext();
}, [emblaApi]);
const onSelect = useCallback(() => {
if (!emblaApi) return;
setSelectedIndex(emblaApi.selectedScrollSnap());
setCanPrev(emblaApi.canScrollPrev());
setCanNext(emblaApi.canScrollNext());
}, [emblaApi]);
// Método para cargar dinámicamente las imágenes
const loadImages = async () => {
const importedImages = [];
for (let i = 1; i <= 5; i++) {
const image = await import(`../assets/torre-promenade/torre-promenade-${i}.jpg`);
importedImages.push(image.default);
}
setImages(importedImages);
};
useEffect(() => {
loadImages();
}, []);
useEffect(() => {
if (emblaApi && images.length > 0) {
emblaApi.reInit(); // Reinicializar Embla Carousel después de cargar las imágenes
emblaApi.on("select", onSelect); // Establecer el evento select después de reinicializar
onSelect(); // Llamar a onSelect inicialmente para establecer canPrev y canNext
setScrollSnaps(emblaApi.scrollSnapList()); // Establecer los puntos de navegación
}
}, [emblaApi, images, onSelect]);
return (
<div className="embla rounded max-w-lg">
<div className="embla__viewport" ref={emblaRef}>
<div className="embla__container">
{images.map((src, index) => (
<div key={index} className="embla__slide">
<img
src={src}
alt={`torre-promenade-${index + 1}`}
className="w-max h-max aspect-square"
/>
</div>
))}
</div>
</div>
<div className="flex items-center justify-center gap-2 embla_dots_container z-10">
{scrollSnaps.map((_, index) => (
<DotButton
key={index}
selected={index === selectedIndex}
onClick={() => emblaApi && emblaApi.scrollTo(index)} // Scroll to index
/>
))}
</div>
<button
className="embla__button embla__button--prev disabled:hidden"
onClick={scrollPrev}
disabled={!canPrev}
>
<ChevronLeft />
</button>
<button
className="embla__button embla__button--next disabled:hidden"
onClick={scrollNext}
disabled={!canNext}
>
<ChevronRight />
</button>
</div>
);
};
I tried using another carousel that I have that if it works correctly, just replacing the code but it presents the same error. I also tried using a "loading" so that the carousel is displayed only when the images finish uploading, in case that was the problem, but it didn't work either
You didn't specify what version of Embla Carousel you're using but assuming you're using v8
and up, Embla automatically picks up when slides are added or removed and will re-initialise. You should be able to solve the problem by adding reInit
event listeners and changing your carousel initialisation code into this:
useEffect(() => {
if (!emblaApi) return
const updateScrollSnaps = (emblaApi) => setScrollSnaps(emblaApi.scrollSnapList());
emblaApi
.on("select", onSelect)
.on("reInit", onSelect); // Run onSelect on reInit
.on("reInit", updateScrollSnaps); // Update scrollSnaps on reInit
onSelect();
updateScrollSnaps();
}, [emblaApi]);