Skip to content

Resource

Async data with reactive loading and error state.

Create a resource

A resource runs a fetcher and exposes value, loading and error, all reactive. With a source function, it fetches again whenever the source changes.

const user = resource(
  () => this.userId.value,
  async (id) => (await fetch(`/api/users/${id}`)).json()
);

user.value;    // the data, or undefined
user.loading;  // true while fetching
user.error;    // the error of the last fetch
user.refetch();

value keeps the last data while a refetch runs and after a failed one, so a list does not flash empty. Read loading to show that newer data is on its way.

Without a source, pass only the fetcher: resource(() => fetchPosts()).

Example

This fetcher waits half a second instead of calling a server.

mutate()

mutate() sets the value right away, without fetching. Use it for optimistic updates: show the change first, then roll it back if the server says no.

const previous = comments.value;
comments.mutate((list) => [...list, draft]);
try {
  await save(draft);
} catch {
  comments.mutate(previous);
}

Suspense

Inside a Suspense boundary, pending resources and lazy() components show the boundary's fallback until they resolve.

Suspense({
  fallback: html`<p>Loading</p>`,
  children: () => html`<${Dashboard} />`,
});