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/)

222 lines (207 loc) 8.66 kB
import React, { ReactNode, ReactElement, Component, ReactPortal } from 'react'; interface ForProps<T, U extends ReactNode> { /** Array to iterate over */ each: ReadonlyArray<T> | undefined | null; /** RenderProp for children generation * OR a static element displayed each.length times */ children: ReactNode | ((item: T, idx: number) => U); /** Fallback item, displayed if *each* has zero length, or isn't an array */ fallback?: ReactNode; } /** Component for mapping an array into collection of ReactNode's * Omits nullish children and provides keys if they're not specified. */ declare function For<T, U extends ReactNode>({ children, each, fallback, }: ForProps<T, U>): ReactElement | null; interface ShowProps<T> { /** predicate */ when: T | undefined | null | false; /** content (or renderProp) to display when predicate is truthy */ children: ReactNode | ((item: NonNullable<T>) => ReactNode); /** content to display when predicate is falsy */ fallback?: ReactNode; } /** Conditional rendering component */ declare function Show<T>({ fallback, ...props }: ShowProps<T>): ReactElement | null; interface SwitchProps { children: ReactNode; /** content to display if no Match predicate is truthy */ fallback?: ReactNode; } /** Component to display one exclusive condition out of many, * using Match component */ declare function Switch(props: SwitchProps): ReactElement | null; interface MatchProps<T> { /** predicate */ when: T | undefined | null | false; /** content (or renderProp) to display if predicate is truthy */ children?: ReactNode | ((item: NonNullable<T>) => ReactNode); } /** Single branch of Switch component. */ declare function Match<T>({ when, children }: MatchProps<T>): ReactElement | null; interface ErrorBoundaryProps { /** renderProp (or static content) to display if error has occured */ fallback?: ReactNode | ((err: unknown, reset: () => void) => ReactNode); /** content to display when no error was catched */ children?: ReactNode; /** callback to call, when an error happens */ onCatch?: (error: unknown, errorInfo: unknown) => void; } interface ErrorBoundaryState { error: unknown; } /** General ErrorBoundary component */ declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> { constructor(props: ErrorBoundaryProps); state: ErrorBoundaryState; static getDerivedStateFromError(error: unknown): { error: unknown; }; componentDidCatch(error: unknown, errorInfo: unknown): void; resetError(): void; render(): ReactNode; } /** This component lets you insert an arbitrary Component or tag and passes * the props through to it. * For example, it can be usefull when you need to conditionally render * <a> or <span> */ declare const Dynamic: <T extends {}>(props: T & { children?: any; component?: string | React.ComponentClass<T, any> | React.FunctionComponent<T> | undefined; } & React.RefAttributes<unknown>) => ReactElement | null; interface PortalProps { mount?: Element | DocumentFragment | string; children?: ReactNode; } /** Component for rendering children outside of the Component Hierarchy root node. */ declare function Portal({ mount, ...props }: PortalProps): ReactPortal | null; 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; } type ResourceState = "unresolved" | "pending" | "ready" | "refreshing" | "errored"; declare 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>; }); static from<T>(data: Promise<T> | Awaited<T> | undefined, pend?: boolean): Resource<T>; /** * 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; } interface AwaitProps<T> { /** resource to wait for */ for: ResourceLike<T>; /** renderProp (or static content) to display while loading */ fallback?: (() => ReactNode) | ReactNode; /** renderProp (or static content) to display if resource was rejected */ catch?: ((err: unknown) => ReactNode) | ReactNode; /** renderProp (or static content) to display when resource is resolved */ children?: ((data: Awaited<T>) => ReactNode) | ReactNode; } /** Component for displaying a Resource */ declare function Await<T>(props: AwaitProps<T>): ReactElement | null; declare class AbortError extends Error { readonly name: "AbortError"; readonly code: 20; constructor(message?: string); } declare class NullishError extends Error { readonly name: "NullishError"; } /** State initializer. * * Either a value, or a function returning a value, for lazy computing. * If state type is a function, then initializer is always lazy. */ type Initializer<T> = T extends Function ? () => T : T | (() => T); type ResourceReturn<T, TArgs extends readonly unknown[]> = [ Resource<T>, { /** Manually set the value. * * If fetcher was currently pending, it's aborted. */ mutate: (v: Awaited<T>) => void; /** * Call refetch with supplied args. * * Fetcher opts added automatically. If fetcher was currently pending, it's aborted. */ refetch: (...args: TArgs) => Promise<T> | T; /** Imperatively abort the current fetcher call. * * If abort is performed with no reason, or with AbortError instance, then * the state is still considered pending/refreshing, resource.error is * not updated, and onError callback is not called. * Any other reason will result in erorred resource state. * * Resource won't be refetched untill deps change again. */ abort: (reason?: any) => void; } ]; type ResourceOptions<T> = { /** Initial value for the resource */ initialValue?: Initializer<Awaited<T>>; /** resolve callback */ onCompleted?: (data: Awaited<T>) => void; /** rejection callback */ onError?: (error: unknown) => void; /** Skip first run (before params change) */ skipFirstRun?: boolean; /** Skip calls of fetcher (can still be called manually with refresh) * * Can be useful if you're waiting for some of deps to be in certain state * before calling the fetcher or if you want to trigger the fetcher only * manually on some event. */ skip?: boolean; /** Don't memoize getter, rerun it every time it changes */ skipFnMemoization?: boolean; }; interface FetcherOpts { /** is true, if the call to fetcher was triggered manually with refetch function, * false otherwise */ refetching: boolean; /** can be used to abort operations in fetcher function, i.e. passed to fetch options */ signal: AbortSignal; } declare function useResource<T, TArgs extends readonly any[]>(fetcher: ((...args: [...TArgs, FetcherOpts]) => Promise<T> | T) | ((...args: TArgs) => Promise<T> | T), deps?: [...TArgs], { initialValue, onCompleted, onError, skipFirstRun, skip, skipFnMemoization, }?: ResourceOptions<T>): ResourceReturn<T, TArgs>; export { AbortError, Await, Dynamic, ErrorBoundary, For, Match, NullishError, Portal, Resource, type ResourceLike, type ResourceState, Show, Switch, useResource };