Part 36: Loading States, Skeleton Screens & Error UI

Part 36 Technology Updated September 12, 2026

Part 36: Loading States, Skeleton Screens & Error UI

A blank screen or a plain text "Loading..." message creates a jarring user experience. Modern applications use Skeleton Screens that mirror the final layout shape while content loads.


1. Creating an Animated Skeleton Component

export function Skeleton({ className }) {
  return (
    <div className={`animate-pulse bg-gray-200 dark:bg-gray-700 rounded ${className}`} />
  );
}

export function ArticleCardSkeleton() {
  return (
    <div className="p-4 border rounded-lg flex gap-4">
      {/* Thumbnail skeleton */}
      <Skeleton className="w-24 h-24 rounded-md shrink-0" />
      <div className="flex-1 space-y-3">
        {/* Title skeleton */}
        <Skeleton className="h-6 w-3/4" />
        {/* Paragraph lines */}
        <Skeleton className="h-4 w-full" />
        <Skeleton className="h-4 w-1/2" />
      </div>
    </div>
  );
}

2. Implementing Fallback and Retry Flows

export default function ArticleFeed({ data, isLoading, error, onRetry }) {
  if (isLoading) {
    return (
      <div className="space-y-4">
        <ArticleCardSkeleton />
        <ArticleCardSkeleton />
        <ArticleCardSkeleton />
      </div>
    );
  }

  if (error) {
    return (
      <div className="p-6 text-center border border-red-200 bg-red-50 rounded">
        <p className="text-red-700 mb-3">Failed to load articles: {error.message}</p>
        <button onClick={onRetry} className="btn-primary">
          Try Again
        </button>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      {data.map(article => (
        <div key={article.id} className="p-4 border rounded-lg">
          <h3 className="font-bold">{article.title}</h3>
          <p>{article.snippet}</p>
        </div>
      ))}
    </div>
  );
}

Key Takeaways

  • Skeleton screens prevent layout shifts (CLS) and improve perceived performance.
  • Always provide user-friendly error messages accompanied by actionable retry buttons.

In Part 37, we explore Optimistic UI Updates!