@lagudal

Как правильно прописать autoplay для карусели?

Есть такая простая реализация карусели - в примере на реакте, но смысл не в этом.
В общем по кнопкам или по навигации переход сделать несложно, но я хочу добавить еще и autoplay.
Если я его просто добавляю как функцию следующего слайда с таймаутом, то автоплей работает, но если я при этом нажму на кнопку или навигацию, то у меня начинают работать новые экземпляры этой функции, и чем больше я нажимаю на кнопку тем больше таких экземпляров. Т.е. начинает скакать, мелькать, моргать.
Я так понимаю, что нажимая на кнопку надо сначала остановить автоплей, но как?

Код

import React, { useState } from 'react'
import { BsChevronCompactLeft, BsChevronCompactRight, BsDot } from 'react-icons/bs'
import Slide_1 from '../assets/slide1.jpg'
import Slide_2 from '../assets/slide2.jpg'
import Slide_3 from '../assets/slide3.jpg'

const slides = [

  {
    url: Slide_1
  },
  {
    url: Slide_2
  },
  {
    url: Slide_3
  },
];

function Hero() {

  const [currentIndex, setCurrentIndex] = useState(0);

  const prevSlide = () => {
    const isFirstSlide = currentIndex === 0;
    const newIndex = isFirstSlide ? slides.length - 1 : currentIndex - 1;
    setCurrentIndex(newIndex);
  }
  const nextSlide = () => {
    const isLastSlide = currentIndex === slides.length - 1;
    const newIndex = isLastSlide ? 0 : currentIndex + 1;
    setCurrentIndex(newIndex);
  }

  const goToSlide = (slideIndex) => {
    setCurrentIndex(slideIndex);
  }

  const autoPlay = () => {
    setTimeout(function () {
      nextSlide();

    }, 3000);
  }
  autoPlay();

  return (
    <div className='w-full h-auto mx-auto my-8'>
      {/* <div style={{backgroundImage: `url(${slides[currentIndex].url})`}} className='w-full h-full bg-center bg-cover border-gray-100 border-[10px] duration-500'></div>*/}

      <div className='w-full max-w-[1280px] h-auto mx-auto duration-500 relative group'>
        <img className='mx-auto border-gray-100 border-[10px]' src={slides[currentIndex].url} alt="" />
        {/* left arrow */}
        <div className='opacity-30 group-hover:opacity-100 absolute top-[50%] -translate-x-0 translaty-[-50%] left-5 text-2xl rounded-full p-2 bg-black/20 text-white cursor-pointer'>
          <BsChevronCompactLeft onClick={prevSlide} size={30} />
        </div>

        {/* right arrow */}
        <div className='opacity-30 group-hover:opacity-100 absolute top-[50%] -translate-x-0 translaty-[-50%] right-5 text-2xl rounded-full p-2 bg-black/20 text-white cursor-pointer'>
          <BsChevronCompactRight onClick={nextSlide} size={30} />
        </div>
      </div>

      <div className="flex top-4 justify-center py-2">
        {slides.map((slide, slideIndex) => (
          <div key={slideIndex} onClick={() => goToSlide(slideIndex)} className='text-2xl cursor-pointer'>
            <BsDot />
          </div>
        ))}
      </div >
    </div>
  )
}

export default Hero

  • Вопрос задан
  • 53 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
useEffect(() => {
  const timeoutID = setTimeout(nextSlide, 3000);
  return () => clearTimeout(timeoutID);
}, [ currentIndex ]);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы