Skip to main content

useAsyncCollection()

import { useAsyncCollection } from '@dr.pogodin/react-global-state';

Resolves and stores at the given path of global state elements of an asynchronous data collection. In other words, it is an auxiliar wrapper around useAsyncData() hook, which uses a loader which resolves to different data, based on an ID argument passed in, and stores data fetched for different IDs in the state.

info

For a given pair of id and path arguments this hook will store at the `${path}.${id}` path of the global state an AsyncDataEnvelopeT object holding the loaded data alongside some related meta-information. That global state segment can be accessed, and even modified using other hooks, e.g useGlobalState(), but doing so you should be careful to not interfere with the related useAsyncCollection() hook logic in an undesireable way.

The TypeScript signature of useAsyncCollection() implementation is

function useAsyncCollection<DataT>(
id: string,
path: null | string | undefined,
loader: AsyncCollectionLoaderT<DataT>,
options: UseAsyncDataOptionsT = {},
): UseAsyncDataResT<DataT>;

This signature is shadowed in TypeScript by several narrowed overloads, explained below, which are necessary to make static TypeScript type analysis work.

TypeScript Overloads

  1. The first TypeScript overload for this hook has the signature (simplified by ommitting details behind the DataT definition):

    function useAsyncCollection<
    StateT,
    PathT extends null | string | undefined,
    IdT extends string,
    >(
    id: IdT,
    path: PathT,
    loader: AsyncCollectionLoaderT<DataT>
    >,
    options?: UseAsyncDataOptionsT,
    ): UseAsyncDataResT<DataT>;

    with three generic parameters:

    • StateT — The type of global state content.
    • PathTnull | string | undefined — The type of path argument.
    • IdTstring — The type of id argument.

    The type DataT is auto-evaluated by TypeScript based on generic parameters, if possible, and used for type-checking the loader and result. If DataT cannot be auto-evaluated, it falls back to void, forbidding TypeScript to use this hook overload.

    tip

    As StateT parameter cannot be evaluated from hook arguments / result types, to use this hook variant directly one would need to provide all three generic parameters explicitly:

    useAsyncCollection<StateT, typeof path, typeof id>(id, path, loader);

    Instead of this, you should prefer to use the withGlobalStateType() function to get and use a specially wrapped version of this hook, with "locked-in" StateT type, which allows TS to auto-evaluate the values of PathT and IdT from given arguments, and thus allows to use the hook this way:

    const { useAsyncCollection } = withGlobalStateType<StateT>();

    // Behind the scene, TS still attempts to auto-evaluate the DataT type
    // based on StateT, typeof id, and typeof path; and uses it to type check
    // the `loader` and result. It will deny to compile it if the type check
    // fails, or DataT cannot be auto-evaluated.
    useAsyncCollection(id, path, loader);
  2. Another overload has the following signature (simplified by omitting details behind the exact DataT definition), which allows to force any DataT type under the caller's discretion:

    function useAsyncCollection<
    Force extends ForceT | false = false,
    DataT = unknown,
    >(
    id: string,
    path: null | string | undefined,
    loader: AsyncCollectionLoaderT<DataT>,
    options?: UseAsyncDataOptionsT,
    ): UseAsyncDataResT<DataT>;

    Generic parameters are:

    • ForcedForceT | false — The default value, false, forbids TypeScript to use this overload (it does so by forcing DataT to evaluate as void behind the scene). It must be set ForceT explicitly, to use this overload.
    • DataT — The type of collection item, defaults to unknown.

    You can use this overload in either of these way:

    // Variant #1.

    import { type ForceT, useAsyncCollection } from '@dr.pogodin/react-global-state';

    useAsyncCollection<ForceT, DataT>(id, path, loader);

    // Variant #2. Using withGlobalStateType().

    import { type ForceT, withGlobalStateType } from '@dr.pogodin/react-global-state';

    const { useAsyncCollection } = withGlobalStateType<StateT>();

    // This overload does not really use StateT for type-checks, it just assumes
    // the DataT type you have specified.
    useAsyncCollection<ForceT, DataT>(id, path, loader);

Arguments

  • idstring — ID of the collection item to load & use.
  • pathnull | string | undefined — The global state path where entire collection should be stored.
  • loaderAsyncCollectionLoaderT — A loader function, which takes an ID of data to load, and resolves to the corresponding data.
  • optionsUseAsyncDataOptionsT — Optional object with additional settings.

Result

Returns an object of UseAsyncDataResT<DataT> type.