Askr
Routing & Data

Resources

Use resources with the current published Askr packages.

  • @askrjs/askr/resources0.0.59

How to use resources

Use a resource for cancellable work whose lifetime belongs to the current component render and dependencies.

  1. Import the published @askrjs/askr/resources entrypoint.
  2. Keep resources configuration next to the component, route, or server composition root that owns it.
  3. Handle pending, unavailable, cancellation, and failure states, then verify the production path.
import { resource } from '@askrjs/askr/resources';

const project = resource(
  ({ signal }) => api.projects.get(projectId(), { signal }),
  [projectId]
);

Resource ownership

resource(fn, deps) is called at the point in the tree that needs the data, and the ResourceResult<T> it returns — value, pending, error, and a refresh() function — belongs entirely to that call site. Nothing about a resource is shared automatically; two components calling resource() with the same arguments run two independent fetches. That's a deliberate tradeoff: no cache to reason about, no risk of one component's refresh affecting another's.

Dependencies

The second argument to resource() is a dependency array, typed as a readonly tuple, and it works the same way effect dependencies do elsewhere: change any value in it and the fetch function reruns. Keep the array limited to values that should actually trigger a refetch — an id or a filter value — rather than objects that change identity on every render.

Pending and failure state

ResourceResult<T> exposes pending as a plain boolean and error as Error | null, so a component checks data.pending, then data.error, before touching data.value. There's no separate stale state here the way queries have — a resource is either loading, failed, or has a value, which keeps the branching simple for the local, non-shared data resource() is meant for.

Cancellation

The function passed to resource() receives an AbortSignal in its options object, and that signal fires whenever the dependency array changes or the calling component unmounts before the fetch finishes. Passing that signal straight through to fetch() (or any AbortSignal-aware API) means an outdated response can't overwrite the value from a newer request — you don't have to track request identity yourself to avoid race conditions.