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.