Reputation: 3562
So I have an application that I'm building using the Create-React-App (CRA).
In one of my components I need to render 18 images, rather small images though. This is how I am currently doing that.
renderImages() {
return someArray.map((someValue, index) => {
let image = require(`../images/${someValue}.png`);
return (
<Image src={image} key={index} />
);
});
}
Basically, I'm looping through an array that has all the names of the png's, and each loop I'll require()
each and every image, total of 18. This is terribly inefficient as these images are trying to be required when the component has already been mounted. As result, the images will not show from 1seconds to 5seconds; it's rather erratic.
So I did some research to see how to do this properly, and apparently I should be loading the images using a webpack configuration. Sound good, but there's a problem. I'm using CRA, and I'm not allowed to touch any of the webpack configuration as a result.
Then it was suggested by someone that you can eject your application from CRA. So I looked into it, and came across this post which stated:
Don't eject! CRA hides a lot of stuff under the hood and ejecting throws it up. It's relatively easier to just clone your src into another project with the tooling setup done.
Now, I'm in a bind. I don't want to eject my application from CRA and lose all the functionality that comes with it, but the inefficient code of using require for each and every image is bothersome.
Question: How can I load these static images properly, either working around CRA, or reworking my code. What would you guys suggest I do?
Upvotes: 0
Views: 1423
Reputation: 728
Browser downloads images only once. So you can use help function like this one, to download all your images before you call renderImages()
.
function asyncDownloadImages(images) {
var listOfImages = images.slice();
var blankImage = new Image();
function downloadNextImage() {
var path = listOfImages.shift();
blankImage.src = path;
}
blankImage.onload = function() {
if (listOfImages.length) {
downloadNextImage();
}
}
downloadNextImage();
}
var listOfImages = [
'https://cdn-images-1.medium.com/max/1600/1*I9pLj7mYf8LC908Zi1JYzg.png',
'https://cdn-images-1.medium.com/max/1600/1*0klm8TN3bY1pa_CmeNBuCw.png',
'https://cdn-images-1.medium.com/max/1600/1*-9mT3HJF6ZEpXiioSxD0Kg.png',
];
asyncDownloadImages(listOfImages);
I wrote some demo code for you. Please check it on jsbin. So you can see in dev tools that images were downloaded only once before DOM node "root" get markup with image nodes which have the same urls in src attribute.
Also you can improve this function and add callback function to arguments, that will call when all images downloaded. If it necessary ;)
Upvotes: 1