Skip to content

Solid.js Suspense and Resources — Async Data Loading

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Solid.js Suspense and Resources. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn Solid.js Suspense and Resources: fetch async data with createResource, show loading states with Suspense, and handle errors gracefully.

In this lesson, you'll use createResource to fetch async data and <Suspense> to show loading states while data loads.

What You'll Learn

How to create resources, use Suspense for loading states, handle errors, refetch data, and combine resources.

Why It Matters

Async data loading is essential for most applications. createResource integrates async data with Solid.js's reactive system, automatically triggering updates.

Real-World Use

Doda Browser's tab preview loads page metadata via createResource, showing a "Loading preview..." state while fetching.

flowchart LR
    A[createResource] --> B[Async Fetch]
    B -->|Loading| C[Suspense Fallback]
    B -->|Done| D[Display Data]
    B -->|Error| E[Error UI]
    style A fill:#2c4f7c,color:#fff

Basic Resource

import { createResource, Suspense } from "solid-js";

async function fetchUser(id) {
  const res = await fetch(`https://api.example.com/users/${id}`);
  return res.json();
}

function UserProfile(props) {
  const [user] = createResource(() => props.id, fetchUser);

  return (
    <Suspense fallback={<p>Loading user...</p>}>
      <h1>{user().name}</h1>
      <p>Email: {user().email}</p>
    </Suspense>
  );
}

Resource with Error Handling

const [user, { mutate, refetch }] = createResource(
  () => props.id,
  async (id) => {
    const res = await fetch(`/api/users/${id}`);
    if (!res.ok) throw new Error("User not found");
    return res.json();
  }
);

// Access error state
// user.error - contains the thrown error

Refetching

function RefreshableProfile(props) {
  const [user, { refetch }] = createResource(
    () => props.id,
    fetchUser
  );

  return (
    <div>
      <Suspense fallback={<p>Loading...</p>}>
        <Profile data={user()} />
      </Suspense>
      <button onClick={() => refetch()}>Refresh</button>
    </div>
  );
}

Multiple Resources

function Dashboard() {
  const [user] = createResource(fetchUser);
  const [posts] = createResource(fetchPosts);
  const [metrics] = createResource(fetchMetrics);

  return (
    <Suspense fallback={<p>Loading dashboard...</p>}>
      <UserProfile user={user()} />
      <PostList posts={posts()} />
      <MetricsChart data={metrics()} />
    </Suspense>
  );
}

Common Mistakes

  1. Not providing a source function: The first argument to createResource is a function that returns the source. If the source never changes, pass () => id.
  2. Forgetting Suspense: Resources must be wrapped in <Suspense> to handle loading states. Without it, accessing user() during loading throws.
  3. Not handling errors: Resources can fail. Check user.error or wrap in an error boundary.
  4. Calling createResource inside conditionals: Resources should be created at the top level, not inside loops or conditions.
  5. Not using refetch for refresh: Create a new resource for refetching, or use the refetch method returned by createResource.

Practice Questions

  1. What does createResource return? Answer: A tuple [resource, { mutate, refetch }] where resource is a signal-like getter for the async data.

  2. What is the purpose of Suspense? Answer: To show fallback content while async resources are loading.

  3. How do you refetch resource data? Answer: Call refetch() from the second element of the returned tuple.

  4. What happens if you access a resource during loading? Answer: It throws a promise that Suspense catches to show the fallback.

Challenge

Build a dashboard that loads user profile, notifications, and recent activity simultaneously using three resources. Show a global loading state until all three resolve.

Mini Project

Create a paginated data browser with createResource: load the first page, show loading while fetching, navigate between pages, and show empty state for no results.

FAQ

Can I use createResource with POST requests?

: Yes. The fetcher function receives the source value. Make any HTTP request and return the result.

Does createResource support Caching?

: Not built-in. Implement caching with signals or use a library like TanStack Query with Solid.js Adapter.

How do I cancel in-flight requests?

: Return an abort function from the fetcher. Solid.js calls it when the resource source changes.

Can I use createResource without Suspense?

: Yes. Check resource.loading for manual loading state handling.

What's Next

Learn about Solid.js Routing for client-side navigation and routing.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro