Home > Back-end >  React losing variable inside of useEffect?
React losing variable inside of useEffect?

Time:10-06

I am trying to implement an image slideshow. setInterval is used inside of useEffect to change the image after x seconds. The currentImage state is holding the current image and after x seconds it will change into the next image but react is telling me that the index variable will be lost after each render.

  const images = [one, two, three, four, five, six, seven];

  const [currentImage, setCurrentImage] = React.useState();

  let index = 0;

  useEffect(() => {
    setInterval(() => {
      if (index < images.length) {
        setCurrentImage(images[index]); 
        index  ; 
        console.log(images[index]);
      } else {
        index = 0; // If so, reset the index
      }
    }, 5000);
  }, []);


<Grid
      item
      xs={false}
      sm={4}
      md={7}
      sx={{
        backgroundImage: `url(${currentImage})`,
        backgroundRepeat: "no-repeat",
        backgroundSize: "cover",
        backgroundPosition: "center",
      }}
    ></Grid>

Assignments to the 'index' variable from inside React Hook React.useEffect will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside React.useEffect

CodePudding user response:

Just use useState to change the index , and remember to clear the timer.

const images = [one, two, three, four, five, six, seven];
    
      const [currentImage, setCurrentImage] = React.useState();
      const [index,setIndex] = useState(0)
      
      useEffect(() => {
       let timer = setInterval(() => {
          if (index < images.length) {
            setCurrentImage(images[index]); 
            setIndex(prev=>prev 1)
            console.log(images[index]);
          } else {
            setIndex(0) // If so, reset the index
          }
        }, 5000);
          return () => {
            clearTimeout(timer)
          }
      }, []);
    
    
    <Grid
          item
          xs={false}
          sm={4}
          md={7}
          sx={{
            backgroundImage: `url(${currentImage})`,
            backgroundRepeat: "no-repeat",
            backgroundSize: "cover",
            backgroundPosition: "center",
          }}
        ></Grid>

Also you can do this :

const images = [one, two, three, four, five, six, seven];
    
     
      const [index,setIndex] = useState(0)
      
      useEffect(() => {
       let timer = setInterval(() => {
          if (index < images.length) {
            setIndex(prev=>prev 1)
            console.log(images[index]);
          } else {
            setIndex(0) // If so, reset the index
          }
        }, 5000);
          return () => {
            clearTimeout(timer)
          }
      }, []);
    
    
    <Grid
          item
          xs={false}
          sm={4}
          md={7}
          sx={{
            backgroundImage: `url(${images[index]})`,
            backgroundRepeat: "no-repeat",
            backgroundSize: "cover",
            backgroundPosition: "center",
          }}
        ></Grid>

CodePudding user response:

Use setTimeout and add the index in the dependency array of your useEffect. In that setTimeout you will update your index. But dont store your index as a variable, store it in state.

  • Related