rcbyr / keen-slider

The HTML touch slider carousel with the most native feeling you will get.
https://keen-slider.io/
MIT License
4.66k stars 213 forks source link

Weird Sizing #185

Closed calvinsomething closed 2 years ago

calvinsomething commented 2 years ago

I am just starting to look at this library, and I was having a lot of problems. So I just went back and started by copying and pasting the whole "Thumbnails" example from here: https://codesandbox.io/s/github/rcbyr/keen-slider-sandboxes/tree/v6/navigation-controls/thumbnails/react-typescript?file=/src/App.tsx

I made some minor adjustments to test it out. Here is my code:

import React, { MutableRefObject, useEffect, useState } from "react";
import "./styles.css";
import { useKeenSlider, KeenSliderPlugin, KeenSliderInstance } from "keen-slider/react";
import "keen-slider/keen-slider.min.css";
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles((theme) => ({
    gallery: {
        position: "absolute",
        top: "20%",
        backgroundColor: "grey",
        width: "50%",
    },
}));

function ThumbnailPlugin(mainRef: MutableRefObject<KeenSliderInstance | null>): KeenSliderPlugin {
    return (slider) => {
        function removeActive() {
            slider.slides.forEach((slide) => {
                slide.classList.remove("active");
            });
        }
        function addActive(idx: number) {
            slider.slides[idx].classList.add("active");
        }

        function addClickEvents() {
            slider.slides.forEach((slide, idx) => {
                slide.addEventListener("click", () => {
                    if (mainRef.current) mainRef.current.moveToIdx(idx);
                });
            });
        }

        slider.on("created", () => {
            if (!mainRef.current) return;
            addActive(slider.track.details.rel);
            addClickEvents();
            mainRef.current.on("animationStarted", (main) => {
                removeActive();
                const next = main.animator.targetIdx || 0;
                addActive(main.track.absToRel(next));
                slider.moveToIdx(next);
            });
        });
    };
}

export default function Gallery() {
    const [sliderRef, instanceRef] = useKeenSlider<HTMLDivElement>({
        initial: 0,
    });
    const [thumbnailRef] = useKeenSlider<HTMLDivElement>(
        {
            slides: {
                perView: 4,
                spacing: 10,
            },
        },
        [ThumbnailPlugin(instanceRef)]
    );

    const [images, setImages] = useState<JSX.Element[]>([]);

    useEffect(() => {
        for (let i = 0; i < 6; i++) {
            setImages((images) => [
                ...images,
                <img src="https://media.istockphoto.com/photos/mens-shirt-picture-id488160041" alt="test" />,
            ]);
        }
    }, []);

    const classes = useStyles();

    return (
        <>
            <div className={classes.gallery}>
                <div ref={sliderRef} className="keen-slider">
                    {images.map((img, i) => (
                        <div className="keen-slider__slide" key={i.toString()}>
                            {img}
                        </div>
                    ))}
                </div>

                <div ref={thumbnailRef} className="keen-slider thumbnail">
                    <div className="keen-slider__slide number-slide1" key="1">
                        1
                    </div>
                    <div className="keen-slider__slide number-slide2" key="2">
                        2
                    </div>
                    <div className="keen-slider__slide number-slide3" key="3">
                        3
                    </div>
                    <div className="keen-slider__slide number-slide4" key="4">
                        4
                    </div>
                    <div className="keen-slider__slide number-slide5" key="5">
                        5
                    </div>
                    <div className="keen-slider__slide number-slide6" key="6">
                        6
                    </div>
                </div>
            </div>
        </>
    );
}

Here is the issue: img

Why are all the images showing at once? When I resize the window the problem is corrected. But that is the first view when loading the page...

Thank you.

rcbyr commented 2 years ago

Hey @calvinsomething

the problem is that your images/slides are not present when the slider is initialized. It has to be updated afterwards. You could also create a component that implements the slider so that the slider is rendered only when the images are loaded. I have created an example that uses a plugin to update the slider. See here: https://codesandbox.io/s/awesome-feistel-o3g9n?file=/src/App.tsx

calvinsomething commented 2 years ago

Thank you!