Using the image tag in React

By Dave Ceddia

In React, image tags are a bit weird. This isn’t really React’s fault, but more a problem of where the images will reside on the server after the app is built.

I’m talking about the plain old <img src=""/> tag here. The same one you’d use in HTML.

When you img in a React component, the the src prop needs to be point at something that the server can serve.

Don’t Use a File Path From Your Computer

A common mistake for beginners is to set the src to a file path on their computer, like /Users/yourname/Projects/this-react-app/src/image.png. That won’t work.

Browsers are mostly sandboxed these days and won’t let you access files by their path on disk. If you did get that to work (maybe with file://), it’d break as soon as you deployed the app, because a web server won’t have that file in the same place! (And no, the solution is not to put it in the same place on the server :)

Two Ways to Include an Image in a React Component

With React, since there’s a build step, you need a way to include the image. There are 2 main ways to do that.

I’m going to assume a Create React App project here, where everything in the public directory gets copied to the server and everything under src is fair game for importing into JS files.

Option 1: import the image into the component

Put the image file somewhere under the src folder. This alone will not automatically make it available, so you have to import the image into the React component where you’re using it.

import companyLogo from './path/to/logo.jpg';

Then you can reference it by that variable name. The name can be anything you want, it doesn’t have to match the image or anything.

Wherever you want to display the image, render your img tag and pass that variable as the src:

function Home() {
  return (
    <div>
      <img src={companyLogo} alt="BigCo Inc. logo"/>
    </div>
  );
}

Note I’m using src={companyLogo} and not src="companyLogo"! If you use the quoted string "companyLogo" it will try to fetch a file at /companyLogo and that will fail. Make sure to use curly braces if you’re using an imported image. Curly braces are the way to pass JS variables as props.

Option 2: Put the image in the public directory

You can put the image file in the public folder (or if this is not Create React App… then any folder that will be copied to the server).

Then, assuming your server is treating the public folder as the “root” directory (/), then your images will be available relative to that – just like with plain HTML.

So if you had an image at public/images/thing.jpg, you could display that image this way:

function Home() {
  return (
    <div>
      <img src="images/logo.jpg" alt="BigCo Inc. logo"/>
    </div>
  );
}

Because this method makes the image available as a regular file on the web server, and you can test it by opening http://localhost:3000/images/logo.jpg in the browser (or, you know, your actual domain name, once it’s deployed!)

How Imported Images Work in React

First, know that imports are not handled by React at all – they’re handled by your bundler, which is probably Webpack. (if you’re using Create React App, it is definitely Webpack)

Webpack, Rollup, Parcel, and other bundlers all work conceptually the same way: when you import a static file, like an image or a CSS file, the bundler doesn’t literally paste that file in at the import location. Instead, it makes a note that this particular JS file depends on this particular image/CSS file/whatever.

Then the bundler will copy the image to the output directory with a generated unique name (like a5c8d3f89cad.jpg) and, behind the scenes, it will replace <img src={yourName}/> with <img src="a5c8d3f89cad.jpg"/>.

If the image is especially small, Webpack might even decide to inline it into the JS bundle, as an optimization.

This all happens without you having to worry about it.

The Best Way to Use the img tag in React?

For one-off images that are related to the component at hand, I like to import them. Imported images have the side benefit that, if the file is missing, the build will fail, and you’ll find out quick! For that reason, I lean toward importing an image if I’m going to use it.

For generic site-wide images, or where it would be annoying to manually import them, I’ll put them in public. This is especially useful when the React app is only a small slice of your overall site, and the same image should be used by both React and other non-React pages. In this case I’d rather avoid duplicating images (with the potential that the copies get out of sync).