Task
@lit-material/taskTask
A reactive controller with no dependencies for async work (usually data fetching) tied to a Lit
host's own reactive properties. It has the same shape as
@lit-labs/task,
written without that dependency: the labs package's API isn't stable, and the actual need
here (run an async function again when its arguments change, track pending, complete and error,
cancel a run a newer one replaced) doesn't need most of what a full task queue ships.
Install
npm install @lit-material/task
Usage
import { TaskController } from "@lit-material/task";
import { LitElement, html } from "lit";
import { customElement, property } from "lit/decorators.js";
@customElement("user-profile")
class UserProfile extends LitElement {
@property() userId!: string;
private readonly userTask = new TaskController(this, {
task: ([id], signal) => fetch(`/api/users/${id}`, { signal }).then((r) => r.json()),
args: () => [this.userId] as const,
});
override render() {
return this.userTask.render({
pending: () => html`Loading…`,
complete: (user) => html`${user.name}`,
error: (e) => html`Error: ${String(e)}`,
});
}
}
API
new TaskController(host, { task, args, autoRun? }):
-
task: (args, signal) => Promise<R>: the async work. Receives anAbortSignalthat fires if a newer run replaces this one before it resolves. -
args: () => T: reads the host's current reactive properties into the task's arguments. Checked before every render; a new run starts by itself whenever this returns a value that differs at the top level. autoRun(defaulttrue): setfalseto run only when you call.run().
Properties: status ("initial" | "pending" | "complete" | "error"),
value, error. Methods: run(args?) (runs now, whatever
autoRun says and whether or not args changed, and aborts any run in flight),
render({ initial?, pending?, complete?, error? }) (picks the matching callback for the
current status).
A newer run always aborts the previous one through the signal passed to task, and an
old run's result or error is dropped even if it arrives after a newer one has resolved, so responses
arriving out of order cause no flicker.
SSR
A TaskController never runs its task during @lit-labs/ssr: SSR drives
willUpdate()/update()/render() directly but never invokes
reactive controllers' hostUpdate(), the hook autoRun relies on to start a
task before the host's first render. So a host rendered on the server always stays in the
"initial" status; the real run starts once the browser hydrates it. Render an
initial state that makes sense before hydration (for example the same as
pending).