UNPKG

react-solid-flow

Version:

[SolidJS](https://www.solidjs.com/docs/latest/api#control-flow)-inspired basic control-flow components and everyday async state hook library for [React](https://reactjs.org/)

89 lines (80 loc) 2.56 kB
export interface ResourceLike<T> { /** Is new data currently loading */ loading?: boolean; /** Resolved resource data for sync access */ data: Awaited<T> | undefined; /** Rejected resource error */ error: unknown; } export type ResourceState = "unresolved" | "pending" | "ready" | "refreshing" | "errored"; export class Resource<T> implements ResourceLike<T> { loading: boolean; data: Awaited<T> | undefined; error: unknown; /** State name * * | state | data | loading | error | * |:-----------|:-----:|:-------:|:-----:| * | unresolved | No | No | No | * | pending | No | Yes | No | * | ready | Yes | No | No | * | refreshing | Yes | Yes | No | * | errored | No | No | Yes | */ state: ResourceState; /** last resolved value * * This can be useful if you want to show the out-of-date data while the new * data is loading. */ latest: Awaited<T> | undefined; constructor(init?: Partial<ResourceLike<T>>, previous?: { latest?: Awaited<T>}) { this.data = init?.data; this.error = init?.error; this.loading = !!init?.loading; if (this.data !== undefined) { this.latest = this.data; } else { this.latest = previous?.latest; } this.state = Resource.getState(this); } static from<T>(data: Promise<T> | Awaited<T> | undefined, pend?: boolean): Resource<T> { const isAsync = data instanceof Promise; return new Resource(isAsync ? { loading: true, } : { data, loading: !!pend, }); } /** * Determine resource-like state, based on its fields values. * * | state | data | loading | error | * |:-----------|:-----:|:-------:|:-----:| * | unresolved | No | No | No | * | pending | No | Yes | No* | * | ready | Yes | No | No | * | refreshing | Yes | Yes | No* | * | errored | No* | No | Yes | * * Values marked with * are expected to equal the specified value, * but actually ignored, when determining the status. */ static getState(r: ResourceLike<unknown>): ResourceState { if (r.data !== undefined && r.loading) { return "refreshing"; } if (r.loading) { return "pending"; } if (r.error !== undefined) { return "errored"; } if (r.data !== undefined) { return "ready"; } return "unresolved"; } }