-1

I'm trying to create a slideshow on my React app using React Hooks but it doesn't seem to be working correctly. My code is as follows:

let i = 0;
const slides = [Slide1, Slide2, Slide3, Slide4]
const [slide, setSlide] = useState(slides[i]);

setInterval(() => {
    if ( i < slides.length - 1) {
        i++;
    } else {
        i = 0;
    }
    setSlide(slides[i])
}, 1000);

The slideshow starts at slide one and goes to slide two correctly and after that it 'glitches' and either doesn't move onto slide three or quickly alternates between slide two and three.

I have also tried this function which produces the same result:

const changeSlide = () => {
    if ( i < slides.length - 1) {
        i++;
    } else {
        i = 0;
    }
    setSlide(slides[i])
};

setInterval(() => changeSlide(), 1000);

I have tried the program with 3, 4 and 5 slides all producing the same result.

Benji
  • 45
  • 8
  • You can refer to this answer https://stackoverflow.com/a/61819969/1577867 It expalins how to use setInterval on a hook – Lahcen Dec 04 '21 at 22:26
  • You misuse the state hook: `useState(slides[i])` initializes the state the very first time, it does not update the state on subsequent re-renders. – Martin Dec 05 '21 at 10:58

1 Answers1

0

setInterval() is a side effect. So if you want use it, you need to call it in useEffect hook and later clean up after using. And inthis case you also should use useRef to change the value of the current index.

  const index = useRef(0);
  const slides = [1, 2, 3, 4]
  const [slide, setSlide] = useState(slides[index.current]);
  
  useEffect(()=>{
    const timer = setInterval(() => {
      if ( index.current < slides.length - 1) {
        index.current++;
      } else {
        index.current = 0;
      }
      setSlide(slides[index.current])
  }, 1000);
  return ()=>{
    clearInterval(timer);
  }
  },[slide])

This code should be fine. And also to simplify your if statement

    const timer = setInterval(() => {
      index.current ++
      setSlide(slides[(index.current + 1)% slides.length])
  }, 1000);
kaemil
  • 24
  • 3
  • Looks good. However, FYI when implemented no slide shows up until the first interval is called after the given time. – Benji Dec 05 '21 at 00:03
  • But if you change time to 10s, slide still show after ~1s hmm..so it's not interval fault. I think it's just render time, but I can be wrong. – kaemil Dec 05 '21 at 10:39