How can I wait until all images are loaded in React.JS?
The problem is that I do some calculations (image processing) using those images and the results are different between multiple refreshes of the browser because at certain times the calculations start before the images are 100% loaded. Is there a way to wait until 100% of all images are loaded?
I've tried something like this:
const [imagesLoaded, setImagesLoaded] = useState(false);
{images.map((image, index) => {
return <ShowImage source={image} index={index+1} key={index} onLoad={() => setImagesLoaded(index)} />
})}
const ShowImage: React.FC<{source:string, index: number, onLoad: () => void}> = ({source, index, onLoad}) => {
return (
<img src={source} width="640" height="480" id={'image' + index} alt={'image' + index} onLoad={onLoad}/>
)
}
And the 'checker':
useEffect(() => {
if(imagesLoaded === 5) {
... do something
}
}, [imagesLoaded]);
But the problem is that this is working only for the first page render, if I refresh is not working, but I refresh one more time is working again and sometimes needs more refreshes, what's the problem?
Your images might not load in the intended order. If your 4th image loads after the 5th one, then the value of imagesLoaded will be 4 at the end.
To prevent that, I would increment the value one at a time, so when all five images are loaded the value will be 5.
onLoad={() => setImagesLoaded(v => v + 1)}
You could refactor your ShowImage component to only set imagesLoaded when the last image source URL is loaded.
function ShowImages({ urls, setImagesLoaded }) {
const onLoad = (index) => {
if (index === urls.length - 1) {
setImagesLoaded(true)
}
};
return (
<>
{urls.map((url, index) => (
<img src={url} onLoad={() => onLoad(index)} key={url} />
))}
</>
);
}
export default ShowImages;
And use the component something like this
const [imagesLoaded, setImagesLoaded] = useState(false);
...
useEffect(() => {
if(imagesLoaded) {
... do something
}
}, [imagesLoaded]);
...
<ShowImages urls={images} setImagesLoaded={setImagesLoaded}/>