# Part 114: Enhancing User Experience with Skeleton UI in Next.js

<figure><img src="https://159896965-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3LclXKUpANLoSt8DPdYV%2Fuploads%2FJK8G3Yjm1qHwjGSqwUcV%2F1675674296261.jpeg?alt=media&#x26;token=989182c4-9098-4bba-8dd9-52aeb4b0f941" alt=""><figcaption><p>[App] Streaming with Suspense</p></figcaption></figure>

When building web applications, the user experience can be greatly enhanced by providing visual feedback during data loading. One effective method is using a "skeleton" UI as a placeholder while the actual data is being fetched. In this blog post, we'll explore how to implement a skeleton UI using Tailwind CSS in a Next.js application, specifically for a comments section that utilizes React's Suspense and Streaming features.

### Understanding the Need for a Skeleton UI

In our previous discussion, we implemented React's Suspense to defer loading a comments section until after the rest of the page content has been displayed. While this approach speeds up the initial load, the default "Loading..." text fallback may not provide the best user experience. A skeleton UI can improve this by offering a visual outline of the content structure, giving users a clearer idea of what's coming.

### Creating a Skeleton Component

We'll create a `CommentListSkeleton` component to serve as a placeholder for the comments section. This component will mimic the structure of the actual comments list but without any real data.

#### Step-by-Step Implementation

1. **Copy the Structure**: Start by copying the existing `CommentList` component and rename it to `CommentListSkeleton`.
2. **Remove Data Fetching**: The skeleton component should render immediately without fetching data. Remove any async operations and props related to real data.
3. **Use Placeholder Elements**: Replace the actual data elements with placeholders. We'll use simple `div` elements styled with Tailwind CSS to represent the user icon and message text.
4. **Add Styling**: Use Tailwind CSS to style the placeholders. We'll add a gray background, rounded corners, and a pulse animation to simulate loading.

Here's the code for the `CommentListSkeleton` component:

```jsx
// components/CommentListSkeleton.jsx

import { UserCircleIcon } from '@heroicons/react/24/outline';

export default function CommentListSkeleton() {
  return (
    <ul className="animate-pulse border mt-3 rounded">
      {[1, 2, 3].map((index) => (
        <li key={index}
          className="border-b px-3 py-2 last:border-none odd:bg-orange-100">
          <div className="flex gap-3 items-center pb-1 text-slate-300">
            <UserCircleIcon className="h-6 w-6" />
            <div className="bg-gray-300 rounded h-3 w-24" />
          </div>
          <p className="py-1">
            <div className="bg-gray-300 rounded h-3 w-2/3" />
          </p>
        </li>
      ))}
    </ul>
  );
}
```

### Integrating the Skeleton with Suspense

To use the `CommentListSkeleton`, integrate it as the `fallback` prop in the Suspense component wrapping the `CommentList`.

<pre class="language-jsx"><code class="lang-jsx">// app/reviews/[slug]/page.jsx
import { Suspense } from 'react';
import CommentForm from '@/components/CommentForm';
import CommentList from '@/components/CommentList';
import CommentListSkeleton from '@/components/CommentListSkeleton';

export default async function ReviewPage({ params: { slug } }) {
  // ...other code

  return (
    &#x3C;>
      {/* ...other content */}
      &#x3C;section>
        &#x3C;h2>Comments&#x3C;/h2>
        &#x3C;CommentForm slug={slug} title={review.title} />
        <a data-footnote-ref href="#user-content-fn-1">&#x3C;Suspense fallback={&#x3C;CommentListSkeleton />}></a>
          &#x3C;CommentList slug={slug} />
        &#x3C;/Suspense>
      &#x3C;/section>
    &#x3C;/>
  );
}
</code></pre>

### Benefits of Skeleton UI

* **Improved User Experience**: Skeleton UI provides a better loading experience by visually representing the content structure.
* **Increased Engagement**: Users are more likely to remain engaged with a page that offers a clear indication of incoming content.
* **Visual Feedback**: Offers users an immediate visual cue that the content is loading, reducing perceived wait time.

### Conclusion

Skeleton UIs are a powerful tool for enhancing user experience during data loading. By providing a visual structure of the page, they help set user expectations and reduce frustration. While this approach is not specific to Next.js, integrating it with Suspense allows for a smooth and responsive experience, making it a valuable addition to any modern web application.

Remember, the goal is to create a seamless experience for users, and a well-implemented skeleton UI can significantly contribute to achieving that.

[^1]:
