Resources
createResource ties an async data flow to a host element's lifecycle. On the client, it starts in each connect pass after attribute sync, the initial render or hydration and @bindTo, just before onConnected(), so the first fetch sees authored prop values. It aborts in-flight work on disconnect and resumes from the current source on reconnect.
Server rendering never connects Element Hosts, so it does not start resource fetches. Fetch server data before rendering and pass resolved values through initialize, prepareHost, or host attributes.
import { createResource } from '@ecopages/radiant';Basic Usage
Fetch once on connect — no reactive source needed:
private data = createResource(this, {
fetcher: (ctx) => fetch('/api/data', { signal: ctx.signal }).then((r) => r.json()),
});Sourced Usage
Drive fetches from a reactive source. Source changes abort the previous request and start a new one.
source only re-runs when it reads a signal (or a host member backed by one). Prefer @state / @prop so plain property access tracks automatically:
@state activeCityId = 'venice';
private weatherQuery = createResource(this, {
source: (ctx) => ctx.host.activeCityId,
fetcher: (cityId, ctx) => fetchWeatherReport(cityId, ctx.signal),
onSuccess: (report) => console.log(report),
});
override render() {
const status = this.weatherQuery.status.get();
const data = this.weatherQuery.data.get();
// ...
}You can also pass a raw signal and call .get() inside source. A plain field is not reactive — changing it will not refetch.
Returning a falsy value (false, null, undefined) from source disables fetching without clearing the current state.
Config Options
| Option | Type | Description |
|---|---|---|
fetcher | (source, ctx) => Promise<Value> | The async function to call. Without source, receives only ctx. With source, the resolved source value is passed as the first argument. ctx provides host and signal. |
source | (ctx) => Source | false | null | undefined | A reactive selector that drives re-fetches. Falsy returns pause fetching. |
initialValue | Value | Seed value exposed from data before the first successful resolution. |
staleTime | number | Milliseconds a successful response stays fresh in the per-instance cache. |
pendingDelay | number | Milliseconds to wait before transitioning status to 'pending'. |
onSuccess | (data, ctx) => void | Called after each successful resolution, including cache hits. |
onError | (error, ctx) => void | Called after each failed resolution. Not called for aborted requests. |
onSettled | (data, error, ctx) => void | Called after each resolution, whether successful or failed. |
Return Value
createResource returns a HostResource that implements AsyncStateResult<Value>:
| Property / Method | Type | Description |
|---|---|---|
data | ReadonlySignal<Value | undefined> | The latest resolved value. |
status | ReadonlySignal<'idle' | 'pending' | 'success' | 'error'> | Current fetch state. |
error | ReadonlySignal<unknown> | The latest rejection reason, if any. |
refetch() | () => void | Re-runs the fetcher from the current source value. |
abort() | () => void | Aborts the in-flight request. |
Lifecycle
- Connect — after the host's first-connect attribute sync, the resource starts observing the source (or fetches immediately if no source is set).
- Source change — the previous request is aborted and a new one starts.
- Disconnect — the in-flight request is aborted. The current state is preserved.
- Reconnect — the resource resumes from the latest source value.
createResource wires these lifecycle steps automatically.
Related
- See Weather App for a full sourced resource example with context.
createResourcebuilds on the package-levelasyncStateprimitive and adds host lifecycle ownership on top.