Importing images in React

Hi everyone,

I’m making a portfolio in React and I have a question.

I have a bunch of pictures I want to use (thumbnail images for projects).
I currently have an array of objects which each have props for each item in the portfolio: a name, an id, an url and an image that will be displayed in a grid. Each of those image keys has a url as its value, but in this case it’s a local file so it’s something like “…/assets/ima01.jps”, etc.
Of course the image is not being displayed.
Is this possible to do this with local files (if so, how?) or do I necesarily have to import every single picture with an import statement? Is the only way around that to upload them somewhere and use the external url in the way I specified above?

Thanks!

1 Like

your question is a bit vague but I will try and guess your intentions.

I take it that your code currently sits on your computer and thus you are able to specify …/assets/ima01.jpg and it works for you, but when you move the code anywhere else (like codepen?) the images appear to be broken.
And you’ve guessed this is because the codepen or github or whatever server currently hosting your code is not also hosting your images?
If this is the issue, then yes, of course you have guessed correctly. Just as the codepen or github server hosts your html and css files, it also needs to host the remaining image files in order for you to refer to them using relative paths (ie. paths that start with …/).
If that is not possible , then you do have to make the images available to that server some other way. For eg. I currently use cloudinary to do that for all my codepen projects. (It is a free file hosting service and that works fine for me).
And yes in that case, you would have to change your relative paths to absolute paths (eg. https://myserver/myfile.jpg instead of …/myfile.jpg)

I hope I guessed your concerns correctly and confirmed your thoughts.

Thanks! But no, that’s not my problem. I am working locally on my files at the moment. I created my app using create-react-app.
My problem is that in order to insert an image in an app made with React, I have to write an import statement for that image, for example:

import image01 from './assets/ima01.jpg'

and then use it anywhere in my code like so:

{image01}

My problem is that I have a big image gallery and it seems unpractical to write a separate import statement for each one of the images. I want to display them dynamically so I have a state object which has the info for each item in my gallery, including a path to the image: ‘…/assets/ima01.jpg’. I want to map out these objects into elements, and the image file should be retrieed by using the img property which is set to the path.

That doesn’t work of course, so I wonder if there is a way around having to write each separate import statement for each separate image when you want to render them dynamically, day by mapping out an array of objects.

I’m sorry that my question was vague! I hope it’s clearer now. Thanks!

1 Like

One pretty simple solution:

// images.js
const images = [
  { id: 1, src: './assets/image01.jpg', title: 'foo', description: 'bar' },
  { id: 2, src: './assets/image02.jpg', title: 'foo', description: 'bar' },
  { id: 3, src: './assets/image03.jpg', title: 'foo', description: 'bar' },
  { id: 4, src: './assets/image04.jpg', title: 'foo', description: 'bar' },
  { id: 5, src: './assets/image05.jpg', title: 'foo', description: 'bar' },
  ...etc
];

export default images;
// MyComponent.js
import images from './images'

//...snip

{ images.map(({id, src, title, description}) => <img key={id} src={src} title={title} alt={description} />)

You’re basically writing a database of images that match the ones in assets.

Then you can be clever in images.js to pull the correct prefix based on the environment if you want. There will be a WebPack plugin that kinda does this as well if you have a google around (you want it to take a directory of files and generate an iterable set of paths to them).

The import as described is more for importing one-off images (logos etc) rather than importing lots of images from a directory.

4 Likes

Thank you! This is exactly what I was looking for.

You can also do this:

// images.js
const images = [
  { id: 1, src: './assets/image01.jpg', title: 'foo', description: 'bar' },
  { id: 2, src: './assets/image02.jpg', title: 'foo', description: 'bar' },
  { id: 3, src: './assets/image03.jpg', title: 'foo', description: 'bar' },
  { id: 4, src: './assets/image04.jpg', title: 'foo', description: 'bar' },
  { id: 5, src: './assets/image05.jpg', title: 'foo', description: 'bar' },
  ...etc
];

function imageLoader() {
  return images;
}

export default imageLoader;
// MyComponent.js
import imageLoader from './images';

// ...snip

this.state = {
  images: []
}

// ...snip

componentDidMount() {
  const images = imageLoader()
  this.setState({images})
}

// render images from state

The reason for that pattern being that you can now, if you want, store your images somewhere like https://cloudinary.com, and really easily swap out the image loader to do this (this is just pseudocode, but hopefully you get the idea):

// images.js
async function imageLoader() {
  const request = await fetch('https://my/images/on/a/cdn');
  const response = await request.json();
  return response.images
}
2 Likes

Hi Dan! Thanks for your response, I had the same issue and I applied this solution, but I couldn’t manage to show the pics! Here’s a snippet from my code:

// MyComponent.js
import assets from './Assets'

.....

<div className="gallery-container">
                {assets.map( ({id, description, img, date},loupe) => (
                    <div className="gallery" key={id}>
                        <img src={loupe} alt="loupe"  className="loupe-img" width="100%" height="100%"/>
                        <img src={img} alt="gallery-img" className="cover"/>
                        <span className='title'>
                            <h4>{description}, {date}</h4>
                        </span>
                    </div>
                ))}
                
            </div>

and this’s the result I’m getting:

could you please help!

Hey Rahim. I’ve just run into the same problem, and found a solution that might work for you too here ~


Basically you store your images in the public folder, and access it with
<img src={process.env.PUBLIC_URL + '/img/logo.png'} />

Hope this helps!

3 Likes

Hi EmmTee, That was very helpful indeed, thanks you!

1 Like

@EmmTee I was looking for this kind of solution, thank you!