createAsync
createAsync
provides a way to fetch data asynchronously and reactively.
Basic Usage
import { createAsync } from "solid-js";
function UserProfile(props: { userId: string }) { const user = createAsync(() => fetchUser(props.userId));
return <div>Name: {user().name}</div>;}
createAsync
will automatically rerun when props.userId
changes.
Loading States
Async signals in Solid v2 don't return undefined
when loading. They always return the resolved value.
To handle initial loading states, wrap the signal read with <Suspense />
.
import { Suspense } from "solid-js";
function UserProfile(props: { userId: string }) { const user = createAsync(() => fetchUser(props.userId));
return ( <Suspense fallback={<div>Loading user...</div>}> <div>Name: {user().name}</div> </Suspense> );}
The Suspense fallback is only shown when UserProfile
is rendered and fetchUser
is pending. It does not trigger when props.userId
changes and fetchUser
reruns.
To handle updates to existing async signals, use isPending
.
import { Suspense, isPending } from "solid-js";
function UserProfile(props: { userId: string }) { const user = createAsync(() => fetchUser(props.userId));
return ( <Suspense fallback={<div>Loading user...</div>}> <div class={isPending(user) ? "loading" : ""}>Name: {user().name}</div> </Suspense> );}
isPending
only returns true
when an existing async signal reruns. It does not trigger when a new async signal is created.
Error Handling
To handle error states, wrap the signal read with <ErrorBoundary />
.
import { ErrorBoundary } from "solid-js";
function UserProfile(props: { userId: string }) { const user = createAsync(() => fetchUser(props.userId));
return ( <ErrorBoundary fallback={<div>Error loading user</div>}> <Suspense fallback={<div>Loading user...</div>}> <div>Name: {user().name}</div> </Suspense> </ErrorBoundary> );}
Reactive tracking inside createAsync
You can only subscribe to dependencies in sync part of your function, i.e. before awaiting promises.
In the following example we fetch random user and trying to refetch the data on button click.
import { createAsync, createSignal, Suspense, isPending } from "solid-js";
const fetchRandomUser = () => new Promise<{ name: string }>((resolve) => { setTimeout(() => resolve({ name: `User ${Math.random()}` }), 1000); });
function IncorrectSubscriptionExample() { const [refetchSignal, refetch] = createSignal(undefined, { equals: false });
const randomUserName = createAsync(async () => { // This is synchronous part of the function (before `await`) const user = await fetchRandomUser(); // after `await` we cannot subscribe to signals anymore // refetch WILL NOT WORK refetchSignal();
return user.name; });
return ( <section> <Suspense fallback={<p>Loading user...</p>}> <p>User name: {randomUserName()}</p> <button disabled={isPending(randomUserName)} onClick={() => refetch()}> Refetch user (not working) </button> </Suspense> </section> );}
function CorrectSubscriptionExample() { const [refetchSignal, refetch] = createSignal(undefined, { equals: false });
const randomUserName = createAsync(async () => { // This is synchronous part of the function (before `await`) // Here we can subscribe to reactive values // refetch WILL WORK refetchSignal();
return (await fetchRandomUser()).name; });
return ( <section> <Suspense fallback={<p>Loading user...</p>}> <p>User name: {randomUserName()}</p> <button disabled={isPending(randomUserName)} onClick={() => refetch()}> Refetch user (working) </button> </Suspense> </section> );}
Last updated: 4/26/25, 4:52 AM
Edit this page on GitHub