This should be fairly simple, but I keep getting a weird behaviour from the result.
Basically, I have an array of images:
const images = [img1, img2, img3, img4, img5, img6];
I also have an image index:
const [imageIndex, setImageIndex] = useState(0);
Then I do a little incrementation of the index:
const switchImage = () => {
if (imageIndex === images.length - 1) {
setImageIndex(0);
} else {
setImageIndex(imageIndex 1);
}
return imageIndex;
}
Then I call this function from a useEffect:
useEffect(() => {
setInterval(() => {
switchImage();
}, 1000);
}, []);
And finally I add the html:
<img src={images[imageIndex]} />
The result is usually it gets stuck on the second image and stops incrementing, so I thought the issue might be with the useEffect and the way the component is rendering, but I've been stuck on it for several hours and it's getting ridiculous.
Thanks for your help in advance!
CodePudding user response:
You need to use the second method signature of the useState
setter function which gives you the previous state value to avoid the stale closure captured value.
const root = ReactDOM.createRoot(document.getElementById('root'));
const images = ['1','2','3','4','5','6'];
const Thing =()=>{
const [imageIndex, setImageIndex] = React.useState(0);
React.useEffect(()=>{
setInterval(() => {
setImageIndex(prev=>prev === images.length - 1?0:prev 1);
}, 1000);
},[])
console.log(imageIndex)
return (
<div>
<h1>{images[imageIndex]}</h1>
</div>
);
}
root.render(<Thing />);
See here https://codepen.io/drGreen/pen/JjpmQrV
Also worth seeing this link which is virtually identical.
CodePudding user response:
In your case the useEffect which you have created it is only being triggered once; when the component is loading - that is because you did not define when this logic should be triggered by adding dependencies to the useEffect.
Now, since the component renders once, 'switchImage'()' is only being triggered once, hence, it iterates once, display the img and stops.
To solve this issue, from what I understand you would like to trigger this logic whenever the index has changed, therefore you need to add 'imageIndex' as a dependency in your useEffect, like this
useEffect(() => {
setInterval(() => {
switchImage();
}, 1000);
}, [imageIndex]);
This way you practically trigger the 'switchImage()' 1. when component is loading and 2. when the index is being updated (every 1 second)
Here is some good documentation on useEffect if you would like to read more about it Using the Effect Hook - React