Solid.js Suspense and Resources — Async Data Loading
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
- Not providing a source function: The first argument to
createResourceis a function that returns the source. If the source never changes, pass() => id. - Forgetting Suspense: Resources must be wrapped in
<Suspense>to handle loading states. Without it, accessinguser()during loading throws. - Not handling errors: Resources can fail. Check
user.erroror wrap in an error boundary. - Calling createResource inside conditionals: Resources should be created at the top level, not inside loops or conditions.
- Not using
refetchfor refresh: Create a new resource for refetching, or use therefetchmethod returned by createResource.
Practice Questions
What does createResource return? Answer: A tuple
[resource, { mutate, refetch }]whereresourceis a signal-like getter for the async data.What is the purpose of Suspense? Answer: To show fallback content while async resources are loading.
How do you refetch resource data? Answer: Call
refetch()from the second element of the returned tuple.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
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