Blog React Guides 13 min read

React Image Fallback Patterns: Missing Src, Failed Loads, and Placeholders

Build a React image fallback component that handles missing src values, failed image loads, layout-safe placeholders, and production-safe fallback.pics URLs.

React image fallbackReact img onerrorReact placeholder imageBroken images
React Image Fallback Patterns: Missing Src, Failed Loads, and Placeholders

React image fallback work has two separate paths: missing image data before render and failed network loads after render.

A reliable component should handle both paths, preserve layout dimensions, avoid error loops, and use generic fallback URL text that is safe for logs and screenshots.

Search intent

Why React image fallback needs more than onError

Most React snippets solve only one case: an image request fails and onError swaps the src. Real applications also receive empty strings, null media fields, deleted CMS assets, expired CDN URLs, and product records without photos.

Treat missing src and failed loads as separate states. Missing data can use the fallback before React renders the img. Failed loads need an onError handler after the browser tries the source.

Missing src

Use the fallback URL before render when the API, CMS, or product record has no image value.

Failed load

Use onError when the browser receives a URL but the resource fails, times out, or returns unusable image data.

Stable UI

Keep width, height, and aspect ratio consistent so the fallback does not introduce layout shift.

Baseline

Basic React img onError fallback

The shortest React image fallback pattern uses onError to replace the current src. Clear the handler first so a failed fallback image cannot trigger a retry loop.

Use currentTarget instead of target in TypeScript examples. React types currentTarget as the img element that owns the handler.

Implementation tsx
const fallbackSrc =
  "https://fallback.pics/api/v1/600x400?text=Image+Unavailable";

export function ProductImage({ src, alt }: { src: string; alt: string }) {
  return (
    <img
      src={src}
      width={600}
      height={400}
      alt={alt}
      onError={(event) => {
        event.currentTarget.onerror = null;
        event.currentTarget.src = fallbackSrc;
      }}
    />
  );
}

Missing data

Handle missing src before the image renders

If the src prop is undefined, null, or an empty string, the browser may not fire the failure path you expect. Decide on the fallback source before rendering the img.

This is the common path for CMS previews, ecommerce imports, user profiles, and API records where media is optional.

Implementation tsx
type ProductImageProps = {
  src?: string | null;
  alt: string;
};

const productFallback =
  "https://fallback.pics/api/v1/800x800/F4F4F5/18181B?text=Product+Image";

export function ProductImage({ src, alt }: ProductImageProps) {
  const imageSrc = src?.trim() ? src : productFallback;

  return (
    <img
      src={imageSrc}
      width={800}
      height={800}
      alt={alt}
      loading="lazy"
      decoding="async"
    />
  );
}

Reusable component

Create a reusable React image fallback component

For production React apps, centralize fallback behavior in one component. That keeps product cards, avatars, article thumbnails, and dashboard previews from each inventing slightly different error handling.

The component below covers missing src values and failed loads while preserving normal img attributes.

Implementation tsx
import type { ImgHTMLAttributes } from "react";

type FallbackImageProps = Omit<
  ImgHTMLAttributes<HTMLImageElement>,
  "src" | "alt"
> & {
  src?: string | null;
  fallbackSrc?: string;
  alt: string;
};

const defaultFallback =
  "https://fallback.pics/api/v1/600x400?text=Image+Unavailable";

export function FallbackImage({
  src,
  fallbackSrc = defaultFallback,
  alt,
  ...props
}: FallbackImageProps) {
  const resolvedSrc =
    typeof src === "string" && src.trim().length > 0 ? src : fallbackSrc;

  return (
    <img
      {...props}
      src={resolvedSrc}
      alt={alt}
      onError={(event) => {
        event.currentTarget.onerror = null;
        event.currentTarget.src = fallbackSrc;
      }}
    />
  );
}

Use cases

Use different placeholders by image surface

One generic fallback is easy to start with, but repeated UI surfaces usually need different dimensions and labels. A product photo fallback should not look like an avatar fallback.

Use deterministic fallback.pics URLs that match the final surface. That makes the UI easier to scan and keeps screenshot tests stable.

Implementation text
<FallbackImage
  src={product.imageUrl}
  fallbackSrc="https://fallback.pics/api/v1/800x800?text=Product+Image"
  width={800}
  height={800}
  alt="Product photo"
/>

<FallbackImage
  src={user.avatarUrl}
  fallbackSrc="https://fallback.pics/api/v1/avatar/96?text=User"
  width={96}
  height={96}
  alt="User avatar"
/>

<FallbackImage
  src={article.coverUrl}
  fallbackSrc="https://fallback.pics/api/v1/1200x630?text=Article+Image"
  width={1200}
  height={630}
  alt="Article cover"
/>

Layout

Prevent layout shift in React image fallbacks

React fallback logic should not change the geometry of the image slot. Keep width and height attributes on the img, and pair them with CSS when the rendered size is responsive.

If the original image slot is square, use a square fallback URL. If it is a social card, use 1200x630. The fallback should preserve the same aspect ratio as the intended image.

Implementation text
<FallbackImage
  className="cardImage"
  src={item.imageUrl}
  fallbackSrc="https://fallback.pics/api/v1/600x400?text=Card+Image"
  width={600}
  height={400}
  alt={item.title}
/>

/* CSS */
.cardImage {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

State

When to use state instead of mutating currentTarget

Directly setting event.currentTarget.src is fine for a small img wrapper. Use React state when the fallback affects other UI, such as showing a badge, changing copy, or reporting the failed source to a logging function.

Avoid setting state repeatedly on every error. Guard against retry loops by checking whether the current source is already the fallback.

Implementation tsx
import { useState } from "react";

const fallbackSrc =
  "https://fallback.pics/api/v1/600x400?text=Image+Unavailable";

export function TrackedImage({ src, alt }: { src?: string; alt: string }) {
  const [imageSrc, setImageSrc] = useState(src || fallbackSrc);
  const [usedFallback, setUsedFallback] = useState(!src);

  return (
    <figure>
      <img
        src={imageSrc}
        width={600}
        height={400}
        alt={alt}
        onError={() => {
          if (imageSrc === fallbackSrc) return;
          setImageSrc(fallbackSrc);
          setUsedFallback(true);
        }}
      />
      {usedFallback ? <figcaption>Image unavailable</figcaption> : null}
    </figure>
  );
}

Privacy

Keep React fallback URL labels safe

It is tempting to include product names, user names, account identifiers, or request IDs in placeholder text. Do not do that. Image URLs can end up in browser history, CDN logs, analytics tools, error reports, and screenshots.

Use generic labels like Product Image, User, Article Image, Preview, or Image Unavailable. Keep private data in your application state, not in the fallback image URL.

Internal links

Where to go next

Use this article when designing the component pattern. Use the shorter React image fallback guide when you need a quick implementation reference, and the API syntax guide when choosing dimensions, colors, avatars, and text labels.

For Next.js applications, use the Next.js fallback guide instead of assuming every img pattern maps directly to next/image behavior.

Implementation text
React guide: https://fallback.pics/guides/react-image-fallback/
HTML onerror guide: https://fallback.pics/guides/img-onerror-fallback/
Next.js guide: https://fallback.pics/guides/nextjs-image-fallback/
Placeholder image API: https://fallback.pics/placeholder-image-api/
Broken image fallback: https://fallback.pics/broken-image-fallback/
API reference: https://fallback.pics/api/

Key takeaways

What to standardize before shipping

  • Handle missing src values before render and failed loads with onError.
  • Clear the image error handler or guard state updates to prevent fallback loops.
  • Centralize React image fallback behavior in a shared component.
  • Match fallback URL dimensions to the final image slot to avoid layout shift.
  • Use generic placeholder text and keep private data out of fallback URLs.

Production fallback layer

Use fallback.pics anywhere an image URL is accepted.

Start with one deterministic URL and standardize fallback behavior across your design system.

Read the docs