Askr documentation
Fundamentals

Component Lifecycle Work

Attach mount, cleanup, and DOM-only work to the component lifecycle so server rendering stays deterministic.

Example

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

import { resource } from '@askrjs/askr/resources';

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

Resources and tasks

resource(fn, deps) from @askrjs/askr/resources runs async work tied to a dependency list and returns { value, pending, error, refresh() } — it reruns automatically whenever deps changes and exposes a refresh() you can call manually. task(fn) is the lower-level primitive for scheduling work as part of a component's lifecycle; the function you pass can itself return a cleanup function or a promise resolving to one, which the runtime calls when the task needs to unwind.

Events and streams

on(target, event, handler, options?) attaches a DOM event listener scoped to the component's lifetime — it wraps addEventListener/removeEventListener so you don't have to write the teardown yourself. stream(source, options?) is the equivalent primitive for values over time, but it's not the same shape as resource — it returns { value, status, pending, stale, error, restart(), close() }, adding a status for connection state (connecting/connected/reconnecting/closed/error) and restart()/close() controls that a one-shot resource() call has no equivalent for.

Timers

timer(intervalMs, fn, options?) runs fn on an interval for as long as the component is mounted, and its when option accepts one or more activity predicates so the timer can pause itself — routeActive(path), documentVisible(), and windowFocused() are the built-in predicates for "only tick while this route is showing," "only while the tab is visible," and "only while the window has focus."

Cancellation and cleanup

resource's worker function receives a { signal } argument — an AbortSignal that fires when the dependencies change or the component unmounts, so an in-flight fetch(url, { signal }) cancels itself instead of racing a newer call. capture(fn) snapshots the result of a synchronous read at call time and returns a thunk to read it back later, which is the documented way to carry a consistent value into an async continuation without re-reading state that may have moved on.