Reputation: 371
I'm trying to render several images from an array, passed onto an "Image" component as a property. However, for whatever reason, the local images I would like to render are not showing up. If I load an image hosted at a web address, that image will show up, indicating that there is nothing wrong with the "imageSource" property being passed onto the Image component. I have tried playing with the source format like so:
let source = 'require(./img/' + props.imageSource + ")";
or trying:
<img src={{uri: source}} role="presentation" style={style.image} />
...but nothing I do makes any difference.
The component is as seen below. I am totally stuck, so help would be much appreciated!
import React from 'react';
let Image = function statelessFunctionComponentClass(props) {
let source = './img/' + props.imageSource;
const style = {
image : {
width: '400pt',
height: '400pt'
}
}
return (
<img src={source} role="presentation" style={style.image} />
)
}
export default Image
Upvotes: 22
Views: 41752
Reputation: 33
I had this issue and found a workaround where I didn't need to put images in my public folder. My folder structure looked something like this.
APP
├──src
├──components
├──ProjectCard.js
├──images
├──pic1.png
├──pic2.png
I passed in my image with from through a prop. I'm using the MaterialUI Card component as a template for this.
You should use require.context()
to point to your folder where the images are stored with the following line. I placed mine below the imports.
const images = require.context('../images', true);
Then, when you are trying to load your image, you should use the following line to use the call. You can replace .png
with .jpg
or whatever image type you are working with.
images(`./${prop.imageName}.png`).default;
Below here is a sample of what this would look surrounded by more code from a custom Material UI Card component, where myprop.imgName
is the name of the image without the filetype.
/* imports */
const images = require.context('../images', true); /* This is the key line 1 */
export default function MyCard({ myprop }) { {*/ Remember to include your props */}
return (
<Card sx={{ maxWidth: 345 }}>
<CardMedia
component="img"
height="140"
image={images(`./${myprop.imgName}.png`).default} {/*Dynamic image loaded via prop*/}
alt={myprop.imgName}
/>
{/* ... other code ... */}
</Card>
);
}
My biggest issue after looking around on StackOverflow was that I needed to include the default
keyword at the end of my images()
call.
Upvotes: 1
Reputation: 316
Mention the image folder path where you have a images. I have created the folder under the 'SRC' folder. So i keep my code like below.
let images = require.context('../../../assets/images', true); let itemImg = images(`./${dynamicObject.photo}`).default;
default is main keyword.
Upvotes: 4
Reputation: 421
Seeing as this question has not been answered, and i was too searching for the answer,
I came across a nifty trick to load images using just a url
Assuming you are using create-react-app plugin
You can use the public folder to render images dynamically
for example, if you put an image with the name "image.jpg" in the public folder of your react app.
you can load it by doing the following
<img src={`${process.env.PUBLIC_URL}/image.jpg`} />
More information can be found below. https://create-react-app.dev/docs/using-the-public-folder
Upvotes: 14
Reputation: 1094
You can include the folder of images by creating a new context with require.context(). From there, you can dynamically access the image you want from that folder, and set it as a src.
Going off of a structure like this:
APP
├──webpack.config.js
├──src
├──containers
├──YourContainer.js
├──components
├──YourComponent.js
├──public
├──bundle.js
├──images
├──dog.png
├──cat.png
In YourContainer.js, you want to create a new context to require that images directory
const images = require.context('../../public/images', true);
From there, you can reference an image specifically:
const dog = images('./dog.png');
or dynamically:
let animal = images(`./${someVariable}.png`);
For a more full example, here's how you can do it while iterating over an object, using the keys to pull your image, and passing that as a style prop to a child component:
let YourContainer = ({ dispatch }) => {
const data = projectData["projectData"];
// Require context image folder
const images = require.context('../../public/images', true);
return (
<div className="container-fluid">
<Row>
{
// Iterate over data object
Object.keys(data).map((keyname, keyindex)=> {
let code = data[keyname]["code"];
let title = data[keyname]["title"];
// Dynamically reference image
// Set as inline style
// Pass as prop to child
let imgsrc = images(`./${code}.png`);
let styler = {
backgroundImage: `url(${imgsrc})`
}
return <YourComponent
key={keyindex}
title={title}
style={styler}
/>
})
}
</Row>
</div>
)
}
Upvotes: 41
Reputation: 1159
The problem you were having was mixing in the local "require" style using relative paths on the filesystem and the URL paths that operate similarly, but slightly differently.
For example:
require('./some-resource.x')
tells the build system to look for a file in the local directory relative to the current file. The important point is that it is the build system that uses this.
When you're in a React component, or any running javascript in the browser, there is no concept of the local disk, only the page/window context within which it is running.
It is not really valid to do the following:
require('/img/some_image.jpg')
nor
<img src="./img/some_image.jpg" />
Because the first refers to the root of the filesystem, which is unlikely to be what you want, and the second refers to a concept which browsers don't really support (disclaimer: they might work with it, I haven't tested it).
I think it is likely that your img
directory is not relative to where the bundle is created.
If you follow the usual structure of having a public
folder, then maybe images
(or img
in your case), then the webserver will serve the public directory according to it's config, which could be http://server/public
or http://server/static
or even just directly under the root address (http://server/
).
In the context of the DOM, which is the page/window context mentioned above, it only makes sense to refer to an image in either the current location, so http://server/path/to/page/img/image.jpg
, or the root location. Either way, you should do something like this:
import React from 'react';
const Image = function statelessFunctionComponentClass(props) {
let source = props.imageIsRelative ?
'img/' + props.imageSource :
'/img/' + props.imageSource;
const style = {
image : {
width: '400pt',
height: '400pt'
}
}
return (
<img src={source} role="presentation" style={style.image} />
)
}
export default Image
Notice that the difference is simply the /
at the front, which indicates whether the path is relative to the current page or the root of the webserver.
Upvotes: 1