1

I am using react-slick for a carousel and have a requirement to disable swiping and dragging of slides after reaching the last image. I research and tried to set swipe: false on the last slide, which worked to disable swiping. However, when I am on the second to last slide and swipe to the last one, it goes to the first slide, then the last slide, and then swiping becomes disabled.

Here is my code:

  const Home: FC<any> = () => {
  const [index, setIndex] = useState(0);
  const sliderRef = useRef<any>(null)
  const slides = [
    { path: "/images/homeScreen/slider1.png", username: "creatorusername1", userlink: "@instagramusername1" },
    { path: "/images/homeScreen/slider2.png", username: "creatorusername2", userlink: "@instagramusername2" },
    { path: "/images/homeScreen/slider3.png", username: "creatorusername3", userlink: "@instagramusername3" },
    { path: "/images/homeScreen/slider1.png", username: "creatorusername4", userlink: "@instagramusername4" },
    { path: "/images/homeScreen/slider2.png", username: "creatorusername5", userlink: "@instagramusername5" },
    { path: "/images/homeScreen/slider6.png", username: "creatorusername6", userlink: "@instagramusername6" },
  ];

  const beforeChange = (prev: number, next: number) => {
    setIndex(next);
  };

  const settings = {
    slidesToShow: 1,
    slidesToScroll: 1,
    arrows: false,
    autoplay: true,
    autoplaySpeed: 2000,
    infinite: false,
    beforeChange,
    edgeFriction: 1,
    swipe : index !== slides.length - 1
  }

  const next = () => {
    sliderRef.current.slickNext();
  };

  const previous = () => {
    sliderRef.current.slickPrev();
  };
  return (
    <>
      <div>
        <section>
          <div className="main-section text-slider">
            <h1 className="title-fade"><Translator label={index === slides.length -1 ? "Rank the world" : "Join The Chain"} /></h1>
            <h4 className="subtitle-fade"><Translator label="New Trends. New Friends." /></h4>
          </div>
          <div className="home-slider">
            <div className="carousel">
              <Slider {...settings} className="carousel-inner" ref={ref => sliderRef.current = ref}>
                {
                  slides.map((slide: any, index) => (
                    <div className="carousel-item" key={index}>
                      <div className="slide-content">
                        <h3>{slide.username}</h3>
                        <span id="user-icon-link">
                          <Link to="/" target="_blank">
                            <img src="/images/homeScreen/instagram.png" alt="link-icon" width="20" height="20" />{slide.userlink}</Link>
                        </span>
                      </div>
                      <img src={slide.path} alt="Chicago" width="1100" height="500" />
                    </div>
                  ))
                }
              </Slider>
              {((slides.length !== 0) && (index !== slides.length - 1)) &&
                <>
                  {(index !== 0) && <a href="#/" className="carousel-control-prev" onClick={previous}>
                    <img src="/images/homeScreen/skipnewbtn.png" alt="Los Angeles" />
                  </a>}
                  {index !== slides.length - 1 && <a href="#/" className="carousel-control-next" onClick={next}  >
                    <img src="/images/homeScreen/fast-forward-button.gif" alt="Los Angeles" />
                  </a>}
                </>
              }
            </div>
          </div>
        </section>
      </div>
      <Footer />
    </>
  )
}
Ed Lucas
  • 5,955
  • 4
  • 30
  • 42
user12660992
  • 59
  • 1
  • 3
  • 12
  • If you set up a codesandbox with this working, then it'll be easier for us to take a look – Luke Storry Jul 21 '20 at 14:06
  • Have you tried changing your state on `afterChange` instead? `const afterChange = (index: number) => { setIndex(index); };` – Ed Lucas Jul 21 '20 at 15:10
  • @EdLucas it worked as you mentioned now issue is that as in the code i am hiding the prev and next arrow on last slide now when i came on last slide prev and next arrows shows then hide which i not a good interaction. Is there any cleaner way. BTW thanks for reply] – user12660992 Jul 22 '20 at 06:25

1 Answers1

1

You could change your state after the next slide has moved into position instead, by using the afterChange() method:

const afterChange = (index: number) => { setIndex(index); };

If you still want to remove an arrow before the last/first slide is shown, you could keep track of two state changes:

const [index, setIndex] = useState(0);
const [nextIndex, setNextIndex] = useState(0);

const afterChange = (index: number) => { setIndex(index); };
const beforeChange = (prev: number, next: number) => { setNextIndex(next); };

...

{(nextIndex !== 0) && 
  <a href="#/" className="carousel-control-prev" onClick={previous}>
    <img src="/images/homeScreen/skipnewbtn.png" alt="Los Angeles" />
  </a>
}
{nextIndex !== slides.length - 1 && 
  <a href="#/" className="carousel-control-next" onClick={next}  >
    <img src="/images/homeScreen/fast-forward-button.gif" alt="Los Angeles" />
  </a>
}

Alternatively, you could keep a state for each button.

const [index, setIndex] = useState(0);
const [showPrevArrow, setShowPrevArrow] = useState(false);
const [showNextArrow, setShowNextArrow] = useState(slides.length > 1);

const afterChange = (index: number) => { setIndex(index); };

const beforeChange = (prev: number, next: number) => { 
  setShowPrevArrow(next > 0);
  setShowNextArrow(next < slides.length - 1);
};

...

{showPrevArrow && 
  <a href="#/" className="carousel-control-prev" onClick={previous}>
    <img src="/images/homeScreen/skipnewbtn.png" alt="Los Angeles" />
  </a>
}
{showNextArrow && 
  <a href="#/" className="carousel-control-next" onClick={next}  >
    <img src="/images/homeScreen/fast-forward-button.gif" alt="Los Angeles" />
  </a>
}

Note: you would no longer need this test in your markup:

((slides.length !== 0) && (index !== slides.length - 1))
Ed Lucas
  • 5,955
  • 4
  • 30
  • 42