My component renders an image every 4 seconds. When I click on the image I want to stop rendering new images. For that I've used a useEffect hook. When I click to the image, the state hasToRefresh
changes it's values, but inside useEffect it doesn't change. This is my code:
import { useEffect, useState } from "react";
const VariableImage = () => {
const imageUrl = "https://picsum.photos/200";
const imageRefresh = "?forcerefresh=";
const [image, setImage] = useState(imageUrl);
const [hasToRefresh, setHasToRefresh] = useState(true);
useEffect(() => {
if (hasToRefresh) {
setInterval(() => {
setImage(imageUrl imageRefresh Math.random());
}, 4000);
}
}, [imageUrl, imageRefresh, hasToRefresh]);
return (
<>
<img
src={image}
onClick={() => setHasToRefresh(!hasToRefresh)}
alt="scenery"
height="200"
width="200"
/>
</>
);
};
export default VariableImage;
Also in sandbox: https://codesandbox.io/s/variable-image-zxhejs
How can I do for when I click the image to not render more images? If anyone could help me I would be very grateful. Thanks.
CodePudding user response:
You're never stopping your interval. And to only trigger the useEffect()
for hasToRefresh
, I would move the creation of image string outside of it.
const VariableImage = () => {
const imageUrl = "https://picsum.photos/200";
const imageRefresh = "?forcerefresh=";
const [imageNumber, setImageNumber] = useState(Math.random());
const image = imageUrl imageRefresh imageNumber;
const [hasToRefresh, setHasToRefresh] = useState(true);
const intervalRef = useRef();
useEffect(() => {
if (hasToRefresh) {
intervalRef.current = setInterval(() => {
setImageNumber(Math.random());
}, 1000);
}
return () => {
intervalRef.current && clearInterval(intervalRef.current);
intervalRef.current = null;
}
}, [hasToRefresh]);
return (
<>
<img
src={image}
onClick={() => setHasToRefresh(!hasToRefresh)}
alt="scenery"
height="200"
width="200"
/>
</>
);
};
Here's the updated codesandbox: https://codesandbox.io/s/variable-image-forked-oxfgc9?file=/src/VariableImage/VariableImage.js:54-896
CodePudding user response:
As Roy Schut mentioned, you never stop your timer. But the best option would be here to stop the timer when the image shouldn't be refreshed. Here's the code I would prefer.
import { useEffect, useState, useRef } from "react";
const VariableImage = () => {
const imageUrl = "https://picsum.photos/200";
const imageRefresh = "?forcerefresh=";
const [image, setImage] = useState(imageUrl);
const [hasToRefresh, setHasToRefresh] = useState(true);
const intervalRef = useRef(null);
useEffect(() => {
startTimer();
return () => stopTimer();
}, []);
const startTimer = () => {
intervalRef.current = setInterval(() => {
setImage(imageUrl imageRefresh Math.random());
}, 4000);
};
const stopTimer = () => {
clearInterval(intervalRef.current);
};
const toggleRefresh = () => {
if (hasToRefresh) {
stopTimer();
} else {
startTimer();
}
setHasToRefresh(state => !state);
};
return (
<>
<img
src={image}
onClick={() => toggleRefresh()}
alt="scenery"
height="200"
width="200"
/>
</>
);
};
export default VariableImage;