Blog Implementation Guides 6 min read

SolidJS Image onerror Fallback for Fast UIs

Add image onerror fallback handling in SolidJS using signals and createEffect, with fallback.pics placeholder URLs for missing and broken media in fast reactive UIs.

solidjs image fallbacksolid js onerrorsolid signalplaceholder imagesolidjs
SolidJS Image onerror Fallback for Fast UIs

SolidJS fine-grained reactivity makes image fallback logic clean and efficient. A signal for the image src, updated in an onError handler, triggers a targeted DOM update without re-rendering the full component tree.

For SolidJS apps with dynamic content or user-generated media, a small fallback component built with createSignal and createEffect covers both missing-at-load-time and failed-to-load scenarios.

Core pattern

createSignal fallback for broken img src

In SolidJS, bind the img src to a signal. In the onError handler, update the signal to the fallback URL. SolidJS updates only the src attribute — not the entire component tree.

Check the current signal value before setting the fallback to prevent an infinite loop if the fallback URL itself returns an error.

Implementation tsx
// components/FallbackImage.tsx (SolidJS)
import { createSignal } from 'solid-js';

interface Props {
  src: string;
  alt: string;
  width: number;
  height: number;
  fallbackText?: string;
}

export function FallbackImage(props: Props) {
  const fallback = () =>
    `https://fallback.pics/api/v1/${props.width}x${props.height}?text=${props.fallbackText ?? 'Not+Found'}`;

  const [src, setSrc] = createSignal(props.src);

  return (
    <img
      src={src()}
      alt={props.alt}
      width={props.width}
      height={props.height}
      onError={() => { if (src() !== fallback()) setSrc(fallback()); }}
    />
  );
}

Reactive props

Handle prop changes with createEffect

SolidJS signals do not automatically track prop changes from the parent. If the parent changes the src prop — for example, when navigating between items in a gallery — the signal stays at its last value.

Use createEffect to watch the incoming src prop and reset the signal when it changes. This ensures the fallback resets correctly for new images.

Implementation tsx
import { createSignal, createEffect } from 'solid-js';

export function FallbackImage(props: Props) {
  const [src, setSrc] = createSignal(props.src);
  const fallback = `https://fallback.pics/api/v1/${props.width}x${props.height}?text=Not+Found`;

  // Reset when src prop changes (e.g., navigating a gallery)
  createEffect(() => { setSrc(props.src); });

  return (
    <img
      src={src()}
      alt={props.alt}
      width={props.width}
      height={props.height}
      onError={() => { if (src() !== fallback) setSrc(fallback); }}
    />
  );
}

Resource pattern

Resolve fallbacks with createResource

When fetching image data from an API, use createResource to handle async state. Derive the image URL from the resource state, substituting a fallback when the resource returns null.

This pattern works well for product pages where the image URL is fetched separately, or for user dashboards where profile data may have an empty avatar field.

Implementation tsx
import { createResource } from 'solid-js';

const [user] = createResource(() => fetchUser(userId));

const avatarSrc = () => {
  const u = user();
  if (!u) return 'https://fallback.pics/api/v1/avatar/64?text=...';
  return u.avatar
    ?? `https://fallback.pics/api/v1/avatar/64?text=${getInitials(u.name)}`;
};

Skeleton state

Show a skeleton placeholder while loading

For images loaded via createResource, display a skeleton placeholder while the resource is loading. Use the fallback.pics animated skeleton URL for a CSS-free loading animation.

Implementation text
<Show
  when={!user.loading}
  fallback={
    <img
      src="https://fallback.pics/api/v1/animated/skeleton/64x64"
      alt="Loading..."
      width="64"
      height="64"
    />
  }
>
  <img src={avatarSrc()} alt={user()?.name} width="64" height="64" />
</Show>

Performance note

Why SolidJS fine-grained reactivity matters for fallbacks

In React, updating state in an onError handler re-runs the whole component function. In SolidJS, updating a signal updates only the bound DOM attribute. For pages with many image slots — product grids, dashboards, comment threads — fallback updates are cheaper.

The practical difference is usually negligible for small pages, but in a virtualized list with hundreds of items, SolidJS's targeted DOM updates prevent unnecessary work across the entire component tree.

Key takeaways

What to standardize before shipping

  • Bind img src to a createSignal and update the signal in onError to trigger a targeted DOM update.
  • Use createEffect to watch the src prop and reset the signal when the parent navigates to a new image.
  • Guard against infinite error loops by comparing the signal value to the fallback before calling setSrc.
  • Use createResource to resolve fallback URLs from async data and Show to display a skeleton during loading.
  • SolidJS's fine-grained updates make fallback handling in large image grids cheaper than React re-renders.

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