Reputation: 571
Have seen a couple of answers online but there are no clear explanations and the solutions don't work. So this is what I am trying to do:
src/assets/images
folderThis is my current way of implementing it (which does not work):
// for example
const imageList = ['img1', 'img2', 'img3' /*...so on */]
const getImagePath = (image) => {
return `../assets/images/${image}.jpg`
}
function ImagesPage() {
return (
<>
<p>Below should show a list of images</p>
{imageList.map((img) => {
return <img src={require(getImagePath(img))} />
})}
</>
)
}
From what I read online, this has something to do with the way webpack works, and this will only work if the exact string path is input into the require
:
// This works:
<img src={require('../assets/images/img1.jpg')} />
// But all these will not work:
<img src={require(getImagePath(img))} />
const img = 'img1.jpg'
<img src={require(`../assets/images/${img}`)} />
Any idea how I can get this dynamic importing of images to work in the scenario I described above? I think this post will be quite helpful to the others searching for an answer too.
Upvotes: 17
Views: 17120
Reputation: 2585
Adding .default will do the trick
<img src={require(`../../folder-path/${dynamic-filename}.png`).default} />
After upgrading to Webpack 5 you will no longer need to append .default
. In fact, quite the opposite. If you keep it, no image is displayed because no src attibut is added to the image.
<img src={require(`../../folder-path/${dynamic-filename}.png`)} />
Upvotes: 27
Reputation: 183
// for example
const imageList = ['img1', 'img2', 'img3' /*...so on */]
const getImagePath = (image) => {
return `../assets/images/${image}.jpg`
}
function ImagesPage() {
return (
<>
<p>Below should show a list of images</p>
{imageList.map((img) => {
return <img src={require(getImagePath(img)).default} />
})}
</>
)
}
If you are using "create react app", adding .default
after require
works fine, it sets all images dynamically from local image folder.
Upvotes: 2
Reputation: 19863
TLDR;
// All of these works
const fileNameExt = 'foo.jpg'
<img src={require('../images/' + fileNameExt)} />
<img src={require(`../images/${fileNameExt}`)} />
const fileName = 'foo'
<img src={require('../images/' + fileName + '.jpg')} />
<img src={require(`../images/${fileName}.jpg`)} />
// These does not work:
const myPathVariable1 = '../images/' + 'foo' + '.jpg'
<img src={require(myPathVariable1)} />
const myPathVariable2 = '../images/' + 'foo.jpg'
<img src={require(myPathVariable2)} />
You can require dynamically with expression.
File names:
const imageList = ["img1", "img2", "img3", ... ]
And to render at UI (add directory path and the extension inside require
):
{
imageList.map(img => {
return <img src={require("../assets/images/" + img + ".jpg")} />
})
}
Why it works?:
Webpack can understand this expression, by generating context about directory and extension, and can load all the matching modules.
Upvotes: 6
Reputation: 12129
Update your getImagePath
function to return an img
element.
const getImage = (image) => {
return <img src={require(`../assets/images/${image}.jpg`)} />
}
Then your map
function would look like this:
imageList.map((img) => {
return getImage(img);
});
Upvotes: 3