React Development

React Images Not Showing Locally? 5 Essential Fixes 2025

Struggling with React images not showing on your local server? Discover 5 essential, up-to-date fixes for 2025. Learn to solve path issues, use the public folder, import images correctly, handle dynamic paths, and fix CSS backgrounds. Get your images displaying in minutes!

L

Liam Carter

Senior Frontend Developer specializing in React, performance optimization, and modern web architecture.

7 min read7 views

Introduction: The Blank Space Where Your Image Should Be

You've meticulously crafted your React component, the logic is flawless, but where your beautiful hero image should be, there's just... nothing. A broken image icon mocks you from the screen. If you're a React developer, you've almost certainly faced this frustrating issue: images not showing up in your local development environment. It’s a common rite of passage, but the good news is that the fix is usually straightforward once you understand how React and its underlying bundler (like Webpack) handle static assets.

In this comprehensive 2025 guide, we'll walk you through the five most common reasons your React images aren't displaying locally and provide clear, actionable fixes to get you back on track. From simple path errors to the nuances of dynamic imports, we've got you covered.

Fix 1: Using the `public` Folder (The Go-To for Static Assets)

The simplest and most direct way to serve static files like images, fonts, or `robots.txt` is by using the `public` folder in your project's root directory. This folder is a special escape hatch from the build process.

How It Works

Any file you place in the `public` folder is not processed by Webpack. Instead, it gets copied directly to the build folder. This means you can reference these files with a direct, absolute path from the root of your domain. When running your app locally, `http://localhost:3000/` becomes your root.

Implementation Steps

  1. Place your image file inside the `public` folder. It's good practice to create an `images` subdirectory, e.g., `public/images/my-logo.png`.
  2. In your JSX, use an `` tag with a `src` attribute that points to the absolute path from the public root. You must use the `%PUBLIC_URL%` environment variable in the HTML file, but in your JSX, you just use a forward slash `/`.

Example:

// File structure:
// public/
// └── images/
//     └── my-logo.png

function Header() {
  return (
    <img src="/images/my-logo.png" alt="My company logo" />
  );
}

When to Use This Method

  • You have a large number of images and don't want them to go through the build process.
  • You need predictable file paths, for example, for a `manifest.json` or favicon.
  • The image is not directly related to a specific component's logic.

Fix 2: Importing Images as Modules (The Webpack Way)

This is the method officially recommended by Create React App (CRA) for images that are part of your component's design. It leverages the power of your module bundler to optimize and manage assets.

How It Works

When you `import` an image file into your JavaScript component, you're not actually getting the image data. Instead, Webpack processes the image and returns a special string—the final path to the image in your `build` folder. This path might look something like `/static/media/my-image.a8h4d9.png`. The bundler handles the file copying, gives it a unique hash to prevent naming conflicts, and ensures it's optimized.

Implementation Steps

  1. Place your image within your `src` directory, often in a dedicated `assets` or `images` subfolder, e.g., `src/assets/images/user-avatar.jpg`.
  2. Import the image at the top of your component file.
  3. Use the imported variable in the `src` attribute of your `` tag, enclosed in curly braces `{}`.

Example:

// File structure:
// src/
// └── components/
//     └── UserProfile.js
// └── assets/
//     └── images/
//         └── user-avatar.jpg

import React from 'react';
import userAvatar from '../assets/images/user-avatar.jpg'; // Note the relative path

function UserProfile() {
  return (
    <div>
      <h3>User Profile</h3>
      <img src={userAvatar} alt="User's profile avatar" />
    </div>
  );
}

Advantages of This Method

  • Error Prevention: If the image is moved or deleted, the `import` will fail, causing a compilation error. This prevents broken images in production.
  • Asset Colocation: You can keep images directly related to a component within that component's folder.
  • Optimization: The build process can optimize the image, reducing its file size.

Fix 3: Checking for Path and Naming Errors (The "Oops" Moment)

Before you dive into more complex solutions, always double-check the basics. A simple typo is often the culprit. This is the most common and easiest-to-fix issue.

Common Path Pitfalls

  • Relative Paths: When importing from the `src` folder, ensure your relative path is correct. `.` refers to the current directory, `..` refers to the parent directory. A common mistake is using `./image.png` when the image is in a parent directory's assets folder, requiring `../assets/image.png`.
  • Public Folder Paths: When using the `public` folder, the path must be absolute from the root (start with a `/`). Do not use relative paths like `../public/images/my-image.png`.
  • File Extension: Did you save it as `.jpg` but are trying to reference `.jpeg` or `.JPG`? Be precise.

Case Sensitivity Matters

Many developers work on Windows or macOS, which often have case-insensitive file systems. You might have a file named `MyImage.png` but reference it as `myimage.png` in your code. This will work fine on your local machine.

However, when you deploy to a Linux-based server (which is most of the internet), its case-sensitive file system will not find the file, resulting in a broken image in production. Always match the case of the filename exactly in your code.

Fix 4: Handling Dynamic Image Paths with `require()`

What if you need to render an image based on props or state? You might be tempted to construct the path string and put it in the `src` attribute, but this often fails with the `import` method.

The Challenge with Dynamic `src`

Webpack needs to know which files to include in the build at compile time. When you do `import myImage from './path/to/image.png'`, Webpack sees it and bundles the image. But if you do ``, Webpack has no idea what the value of `imageName` will be, so it doesn't bundle any of the potential images.

The `require()` Solution

The `require()` function can be used inside your component's render method to dynamically load assets. Webpack is smart enough to understand this pattern and will bundle all possible images that could match the path.

Example:

// Imagine you have a list of products
const products = [
  { id: 1, name: 'Product A', imageName: 'product-a' },
  { id: 2, name: 'Product B', imageName: 'product-b' },
];

function ProductList() {
  return (
    <div>
      {products.map(product => (
        <div key={product.id}>
          <h4>{product.name}</h4>
          <img 
            src={require(`../assets/images/${product.imageName}.png`).default} 
            alt={product.name}
          />
        </div>
      ))}
    </div>
  );
}
// Note: Some bundler setups might not require `.default`

Fix 5: Troubleshooting CSS Background Images

The same principles apply to images used in CSS, but the syntax is slightly different. The problem often arises when a CSS file can't find the image relative to its own location.

CSS with the Public Folder

If your image is in `public/images/background.jpg`, your CSS can reference it with an absolute path from the root.

/* In your App.css file */
.hero-section {
  background-image: url('/images/background.jpg');
}

CSS with JS Imports (Inline Styles)

For images inside the `src` folder, you can import them in your JS file and then pass them to an inline style object. This is a very robust method.

import React from 'react';
import heroBackground from '../assets/images/hero-background.jpg';

function HeroSection() {
  const style = {
    backgroundImage: `url(${heroBackground})`,
    height: '400px',
    backgroundSize: 'cover',
  };

  return <div style={style}>Your content here</div>;
}
Comparison: Image Handling Methods in React
Feature Public Folder Method Import/Module Method
File Location Inside the `public` folder Inside the `src` folder
How it's Handled Copied to build folder as-is; not processed by Webpack. Bundled by Webpack; path is hashed and file is optimized.
JSX Syntax `<img src="/images/file.png" />` `<img src={importedImage} />`
Pros Simple, predictable paths, bypasses build step. Build-time error checking, asset colocation, automatic optimization.
Cons No compile-time checks, no optimization, can clutter public folder. Can be tricky with dynamic paths, adds to build process.
Best For Favicons, `manifest.json`, svgs you want to script, or when you need a stable URL. Component-specific images like logos, icons, avatars, and hero backgrounds.

Conclusion: Putting Images Back in the Picture

A broken image in React is rarely a complex problem. It's almost always a misunderstanding of how the development server and build process handle file paths. By understanding the distinction between the `public` folder and the `src` folder, you can choose the right method for your needs.

Next time you see that dreaded blank space, run through this checklist: Check the path and filename for typos, decide if the image should be in `public` or `src`, use the correct syntax for your chosen method, and leverage `require()` for dynamic cases. With these five fixes in your toolkit, you'll solve image issues in minutes and keep your development workflow smooth and efficient.