maxmarinich / react-alice-carousel

React responsive component for building content galleries, content rotators and any React carousels
MIT License
832 stars 91 forks source link

onSlideChanged is not working. #302

Closed MuraliAirody closed 8 months ago

MuraliAirody commented 8 months ago

I created a custom button, upon cliking on the button slides are not rendering activeIndex is updating properly. If I use the default button and dots it works perfectly, in an onSlideChanged I am not getting an event please provide a solution for this.

"react-alice-carousel": "^2.7.1",

import React, { useState } from "react";
import HomeSectionCard from "../Home_Section_Crad/HomeSectionCard";
import AliceCarousel from "react-alice-carousel";
import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
import { Button } from "@mui/material";
import { mens_kurta } from "../../../Data/Mens/mens_kurta";
import "react-alice-carousel/lib/alice-carousel.css";

function HomeSectionsCarousel() {
  const [activeIndex, setActiveIndex] = useState(0);

  const responsive = {
    0: { items: 2 },
    568: { items: 3 },
    1024: { items: 5 },
  };

  const slidePrev = () => {
    console.log("Previous button clicked");

    setActiveIndex(activeIndex - 1);
    // console.log(activeIndex);
  };
  const slideNext = () => {
    console.log("Next button clicked");

    setActiveIndex(activeIndex + 1);
    // console.log(activeIndex);
  };

  const syncActiveIndex = (e) => {
    console.log(e);
    setActiveIndex(e.item);
  };

  const items = mens_kurta
    .slice(0, 10)
    .map((item) => <HomeSectionCard product={item} />);

  return (
    <div className="relative">
      <div className="relative p-5">
        <AliceCarousel

          items={items}
          disableDotsControls
          disableButtonsControls
          responsive={responsive}
          activeIndex={activeIndex}
          onSlideChanged={(e) => {
            syncActiveIndex(e)
            console.log(e)
        }}
        />
        {activeIndex != items.length - 5 && (
          <Button
            onClick={slideNext}
            variant="contained"
            className="z-50"
            sx={{
              position: "absolute",
              top: "8rem",
              right: "0rem",
              transform: "translate(50%) rotate(90deg)",
              bgcolor: "white",
            }}
            aria-label="next"
          >
            <ArrowBackIosNewIcon
              sx={{ color: "black", transform: "rotate(90deg)" }}
            />
          </Button>
        )}
        {activeIndex != 0 && (
          <Button
            onClick={slidePrev}
            variant="contained"
            className="z-50"
            sx={{
              position: "absolute",
              top: "8rem",
              left: "0rem",
              transform: "translate(-50%) rotate(-90deg)",
              bgcolor: "white",
            }}
            aria-label="next"
          >
            <ArrowBackIosNewIcon
              sx={{ color: "black", transform: "rotate(90deg)" }}
            />
          </Button>
        )}
      </div>
    </div>
  );
}

export default HomeSectionsCarousel;
maxmarinich commented 8 months ago

Hi, @MuraliAirody! I simplified your example and it works as expected, the event fired in both mods (custom and lib buttons).
It looks like the problem is in your code or an external library. Please see custom-components or events examples.

import React, { useState } from 'react';
import AliceCarousel from 'react-alice-carousel';

const items = [
    <div className="item" data-value="1">
        1
    </div>,
    <div className="item" data-value="2">
        2
    </div>,
    <div className="item" data-value="3">
        3
    </div>,
    <div className="item" data-value="4">
        4
    </div>,
    <div className="item" data-value="5">
        5
    </div>,
    <div className="item" data-value="6">
        6
    </div>,
    <div className="item" data-value="7">
        7
    </div>,
    <div className="item" data-value="8">
        8
    </div>,
];

const responsive = {
    0: { items: 2 },
    568: { items: 3 },
    1024: { items: 5 },
};

function HomeSectionsCarousel() {
    const [activeIndex, setActiveIndex] = useState(0);

    const slidePrev = () => {
        // eslint-disable-next-line no-console
        console.log('Previous button clicked');
        setActiveIndex(activeIndex - 1);
    };
    const slideNext = () => {
        // eslint-disable-next-line no-console
        console.log('Next button clicked');
        setActiveIndex(activeIndex + 1);
    };

    return (
        <div className="relative">
            <div className="relative p-5">
                <AliceCarousel
                    items={items}
                    disableDotsControls
                    disableButtonsControls
                    responsive={responsive}
                    activeIndex={activeIndex}
                    onSlideChanged={(e) => {
                                     setActiveIndex(e.item)
                    }}
                />
                {activeIndex != 0 && (
                    <button onClick={slidePrev} className="z-50" aria-label="next">
                        PREV
                    </button>
                )}
                {activeIndex != items.length - 5 && (
                    <button onClick={slideNext} className="z-50" aria-label="next">
                        NEXT
                    </button>
                )}
            </div>
        </div>
    );
}

export default HomeSectionsCarousel;
liliput1209 commented 1 month ago

@MuraliAirody Are you able to find its solution...i am also stuck in the same problem....buttons are working but onSlideChanged is not responding....if you get it...then please let me know

typecaster commented 1 month ago

Fixed using the useRef hook by:

  1. Directly controlling 'activeIndex' state
  2. Using the 'slideTo' method of AliceCarousel to change the slide.

Hope this helps!!!

import AliceCarousel from "react-alice-carousel";
import HomeSectionCard from "../homeSectionCard/HomeSectionCard";
import { Button } from "@mui/material";
import KeyboardArrowLeftIcon from "@mui/icons-material/KeyboardArrowLeft";
import { mens_kurta } from "../../../data/mens_kurta";

export const HomeSectionCarousel = () => {
  const [activeIndex, setActiveIndex] = useState(0);
  const carouselRef = useRef(null);

  const responsive = {
    0: { items: 1 },
    720: { items: 3 },
    1024: { items: 5 },
    1280: { items: 6 },
  };

  const items = mens_kurta.slice(0, 10).map((item) => <HomeSectionCard product={item} />);
  const maxIndex = items.length - 1;

  const slidePrev = () => {
    if (activeIndex > 0) {
      const newIndex = activeIndex - 1;
      setActiveIndex(newIndex);
      carouselRef.current.slideTo(newIndex);
    }
  };

  const slideNext = () => {
    if (activeIndex < maxIndex) {
      const newIndex = activeIndex + 1;
      setActiveIndex(newIndex);
      carouselRef.current.slideTo(newIndex);
    }
  };

  return (
    <div className="border">
      <div className="relative p-5">
        <AliceCarousel
          items={items}
          disableButtonsControls
          disableDotsControls
          responsive={responsive}
          autoPlay
          autoPlayInterval={1500}
          activeIndex={activeIndex}
          ref={carouselRef}
        />
        {activeIndex < maxIndex && (
          <Button
            variant="contained"
            className="z-50 bg-white"
            onClick={slideNext}
            sx={{
              position: "absolute",
              top: "8rem",
              right: "0rem",
              transform: "translatex(50%) rotate(90deg)",
              bgcolor: "white",
            }}
            aria-label="next"
          >
            <KeyboardArrowLeftIcon
              sx={{ transform: "rotate(+90deg)", color: "black" }}
            />
          </Button>
        )}
        {activeIndex > 0 && (
          <Button
            variant="contained"
            className="z-50 bg-white"
            onClick={slidePrev}
            sx={{
              position: "absolute",
              top: "8rem",
              left: "0rem",
              transform: "translatex(-50%) rotate(-90deg)",
              bgcolor: "white",
            }}
            aria-label="prev"
          >
            <KeyboardArrowLeftIcon
              sx={{ transform: "rotate(+90deg)", color: "black" }}
            />
          </Button>
        )}
      </div>
    </div>
  );
};
liliput1209 commented 1 month ago

Fixed using the useRef hook by:

  1. Directly controlling 'activeIndex' state
  2. Using the 'slideTo' method of AliceCarousel to change the slide.

Hope this helps!!!

import AliceCarousel from "react-alice-carousel";
import HomeSectionCard from "../homeSectionCard/HomeSectionCard";
import { Button } from "@mui/material";
import KeyboardArrowLeftIcon from "@mui/icons-material/KeyboardArrowLeft";
import { mens_kurta } from "../../../data/mens_kurta";

export const HomeSectionCarousel = () => {
  const [activeIndex, setActiveIndex] = useState(0);
  const carouselRef = useRef(null);

  const responsive = {
    0: { items: 1 },
    720: { items: 3 },
    1024: { items: 5 },
    1280: { items: 6 },
  };

  const items = mens_kurta.slice(0, 10).map((item) => <HomeSectionCard product={item} />);
  const maxIndex = items.length - 1;

  const slidePrev = () => {
    if (activeIndex > 0) {
      const newIndex = activeIndex - 1;
      setActiveIndex(newIndex);
      carouselRef.current.slideTo(newIndex);
    }
  };

  const slideNext = () => {
    if (activeIndex < maxIndex) {
      const newIndex = activeIndex + 1;
      setActiveIndex(newIndex);
      carouselRef.current.slideTo(newIndex);
    }
  };

  return (
    <div className="border">
      <div className="relative p-5">
        <AliceCarousel
          items={items}
          disableButtonsControls
          disableDotsControls
          responsive={responsive}
          autoPlay
          autoPlayInterval={1500}
          activeIndex={activeIndex}
          ref={carouselRef}
        />
        {activeIndex < maxIndex && (
          <Button
            variant="contained"
            className="z-50 bg-white"
            onClick={slideNext}
            sx={{
              position: "absolute",
              top: "8rem",
              right: "0rem",
              transform: "translatex(50%) rotate(90deg)",
              bgcolor: "white",
            }}
            aria-label="next"
          >
            <KeyboardArrowLeftIcon
              sx={{ transform: "rotate(+90deg)", color: "black" }}
            />
          </Button>
        )}
        {activeIndex > 0 && (
          <Button
            variant="contained"
            className="z-50 bg-white"
            onClick={slidePrev}
            sx={{
              position: "absolute",
              top: "8rem",
              left: "0rem",
              transform: "translatex(-50%) rotate(-90deg)",
              bgcolor: "white",
            }}
            aria-label="prev"
          >
            <KeyboardArrowLeftIcon
              sx={{ transform: "rotate(+90deg)", color: "black" }}
            />
          </Button>
        )}
      </div>
    </div>
  );
};

Yes its working.... it just taking 4 more clicks on slide next button to remove even the slider ends. I am not able to configure the problem now