useAsyncListing

Source
import { useAsyncListing } from "@prestojs/util";
useAsyncListing<ResultT>(props)
Source

Specialised version of useAsync for retrieving a list of paginated values and optionally accumulating them as the next page is retrieved (e.g. for things like infinite scroll).

Unless you are using paginator with accumulatePages, or are writing a hook/component that may use those options based on its props, you don't need this hook and should just use useAsync.

Usage

While it can work with any async function the typical usage would be to use it with an Endpoint that has paginationMiddleware applied.

const list = new Endpoint("/list", {
  middleware: [paginationMiddleware()],
})

function Example() {
  const paginator = usePaginator(list)
  const execute = useCallback(async (args) => {
    return (await list.execute(args)).result
  }, [])
  const { result, isLoading, error } = useAsyncListing({
    execute,
    paginator,
    accumulatePages: true,
  })

  if (isLoading) return <Loading />
  if (error) return <Error error={error} />

  return <List items={result} paginator={paginator} />
}

See the infinite scroll demo for a full working example.

Arguments:

ArgumentTypeDescription
*
props
An object with the properties below
props.accumulatePagesboolean

Whether to accumulate pages as more results are fetched. For example if the first page of results is returned, then the next page is fetched then the combined results for the first two pages will be resolved.

This resets whenever query changes or if pagination state changes to anything other than the next page.

If this is true you must specify paginator.

*props.execute

Asynchronous function that returns the result for the query. Passed an object with query and paginator keys.

Note that when trigger is DEEP changes to this function will cause it to be called again so you must memoize it (eg. with useCallback) if it's defined in your component or hook.

props.paginator|null

Optional paginator if result is paginated. This will be monitored for any state changes which will trigger a call to execute.

Required if accumulatePages is true.

props.queryRecord

Any query string parameters for the request

props.trigger"MANUAL"|"DEEP"

When to trigger the fetch. Defaults to DEEP which means whenever a deep equality check on query or paginator state fails it will refetch.

If set to MANUAL nothing will happen until it changes to DEEP or you call the returned run function. You can use this to defer execution until the value is required.

Defaults to 'DEEP'.

Returns:
An object with these properties:
PropertyTypeDescription
*errornull|Error

Set to the rejected value of the promise. Only one of error and result can be set. If isLoading is true consider this stale (i.e. it's the error from the previous props). This can be useful when you want the UI to show the previous value until the next value is ready.

Until first call has resolved neither error nor result will be set

*isLoadingboolean

True while execute call is in progress.

*paginatornull|

The same paginator passed in to useAsyncListing

*reset

When called will set both result and error to null. Will not immediately trigger a call to the action but subsequent changes to query or paginator will according to the value of trigger.

*resultnull|T

The value returned from execute.

Only one of error and result can be set. If isLoading is true consider this stale (i.e. it's the result from the previous props). This can be useful when you want the UI to show the previous value until the next value is ready.

Until first call has resolved neither error nor result will be set

*run

A function to manually trigger the action. If options.trigger is MANUAL calling this function is the only way to trigger the action.

This function will return a promise that resolves/rejects to same value returned by execute. If accumulatePages is set the value returned is the accumulated value.

Examples

Infinite scroll list

As this list is scrolled to the bottom the next page is fetched. With the accumulatePages option instead of results being replaced with the next page it will have the next page appended to it.