# Resource

Source: https://signy.dev/documentation/1/reactivity/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.

```js
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.

```js
const { Component, Signal, application, html, resource, Show } = Signy;

const users = { 1: "Ada Lovelace", 2: "Grace Hopper", 3: "Alan Turing" };
const fetchUser = (id) =>
  new Promise((resolve) => setTimeout(() => resolve({ id, name: users[id] }), 500));

class Profile extends Component {
  userId = new Signal(1);
  user = resource(() => this.userId.value, fetchUser);

  next() {
    this.userId.set((id) => (id % 3) + 1);
  }

  render() {
    return html`
      <button onClick=${() => this.next()}>Next user</button>
      ${Show({
        when: () => this.user.loading,
        fallback: html`<p>User: ${() => this.user.value?.name}</p>`,
        children: html`<p aria-busy="true">Loading</p>`,
      })}
    `;
  }
}

application(Profile).mount("#resource-user");
```

## 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.

```js
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.

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