LimitOffsetPaginator

Source
import { LimitOffsetPaginator } from "@prestojs/util";
Hierarchy
  • Paginator<,>
  • LimitOffsetPaginator

Limit & offset based paginator

See Paginator for an overview of how state is managed for paginator classes.

There are two supported response shapes by default. The first assumes next and previous are URLs with a 'offset' query parameter. If this shape is encountered the 'offset' query parameter will be extracted:

{
     next: null|'http://example.com/?offset=20',
     previous: null|'http://example.com/?offset=10',
     results: Array,
     limit: 10,
     total: 100,
 }

The other assumes nextOffset and previousOffset are the offset values directly.

{ limit: 10, next: 20, previous: 10, results: Array, total: 100 }

If there's no next or previous page those values should be null.

limit in both is optional.

total or count is required and should be the total number of available records.

Usage

The basic usage outside of React is:

let state = {}
const setState = (nextState) => {
  state = nextState
}
let internalState = {}
const setInternalState = (nextState) => {
  internalState = nextState
}
const paginator = new LimitOffsetPaginator(
  [state, setState],
  [internalState, setInternalState]
)
paginator.setResponse({ limit: 10, total: 10 })
// state == { limit: 10 }
// internalState == { total: 10, responseIsSet: true }
paginator.next()
// state == { limit: 10, offset: 10 }
paginator.setOffset(50)
// state == { limit: 10, offset: 50 }

To use in a component use the usePaginator hook with paginationMiddleware instead. See the Use with usePaginator & paginationMiddleware example.

Examples

Paginate manually

This example shows how to set up a paginator and manually call setResponse. In practice, you would usually use usePaginator and paginationMiddleware, but this shows you how things work internally.

See the next example for the recommended usage.

Use with usePaginator & paginationMiddleware

This example shows the standard usage of a paginator with usePaginator and an Endpoint with paginationMiddleware.

The big difference when using paginationMiddleware is that the result returned no longer includes the pagination state - it only includes the records for that page. Pagination state is stored in the paginator instead.

Store pagination state in the URL.

This example is the same as the previous except it stores the state in the URL. This allows the page to be restored on refresh.

Open the example in a new window to see it in action.

API

Constructor

new LimitOffsetPaginator(?currentStatePair,?internalStatePair)
Source

See the documentation for replaceStateControllers for what currentStatePair and internalStatePair are

Arguments:

ArgumentTypeDescription
currentStatePairnull|[State, ]
internalStatePairnull|[State, ]

Methods

first()
Source

Go to the first page.

Returns:void
firstState()
Source

Return the state for the first page

Does not transition state. To transition state call first instead.

Returns:
An object with these properties:
PropertyTypeDescription
limitnumber|string
offsetnumber|string
getRequestInit(props)
Source

Return the options to use with Endpoint.execute or Endpoint.prepare. Usually this just involves setting query to the query string parameters for the paginator but can also provide custom headers or different URL resolve arguments.

Arguments:

ArgumentTypeDescription
*propsObject

The existing options for the endpoint

Returns:
An object with these properties:
PropertyTypeDescription
bodynull|BodyInit

A BodyInit object or null to set request's body.

cacheRequestCache

A string indicating how the request will interact with the browser's cache to set request's cache.

credentialsRequestCredentials

A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials.

headersHeadersInit|Record

Any headers to add to the request. You can unset default headers that might be specified in the default Endpoint.defaultConfig.requestInit by setting the value to undefined.

integritystring

A cryptographic hash of the resource to be fetched by request. Sets request's integrity.

keepaliveboolean

A boolean to set request's keepalive.

methodstring

A string to set request's method.

modeRequestMode

A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode.

queryRecord

Any query request parameters

redirectRequestRedirect

A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect.

referrerstring

A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer.

referrerPolicyReferrerPolicy

A referrer policy to set request's referrerPolicy.

signalnull|AbortSignal

An AbortSignal to set request's signal.

urlArgsRecord

Any arguments for the URL

windownull

Can only be null. Used to disassociate request from any Window.

hasNextPage()
Source

Returns true if there's more results after the current page

Returns:boolean
hasPreviousPage()
Source

Returns true if there's a previous page

Returns:boolean
last()
Source

Go to the last page.

If the last page is not yet known because results haven't been returned this function does nothing.

Returns:void
lastState()
Source

Return the state for the last page. If the last page isn't yet known (eg. results haven't yet been returned) then null will be returned.

Does not transition state. To transition state call last instead.

Returns:null|
An object with these properties:
PropertyTypeDescription
limitnumber|string
offsetnumber|string
limitState(limit)
Source

Return the state for the specified limit

Does not transition state. To transition state call setLimit instead.

Arguments:

ArgumentTypeDescription
*limitnull|number
Returns:
An object with these properties:
PropertyTypeDescription
limitnumber|string
offsetnumber|string
next()
Source

Go to the next page

Returns:void
nextState()
Source

Return the state for the next page

Does not transition state. To transition state call next instead.

Returns:null|
An object with these properties:
PropertyTypeDescription
limitnumber|string
offsetnumber|string
offsetState(offset)
Source

Return the state for the specified offset

Does not transition state. To transition state call offsetState instead.

Arguments:

ArgumentTypeDescription
*offsetnull|number
Returns:
An object with these properties:
PropertyTypeDescription
limitnumber|string
offsetnumber|string
previous()
Source

Go to the previous page.

Returns:void
previousState()
Source

Return the state for the previous page

Does not transition state. To transition state call previous instead.

Returns:null|
An object with these properties:
PropertyTypeDescription
limitnumber|string
offsetnumber|string
replaceStateControllers(currentStatePair,internalStatePair)
Source

Paginator receives 2 tuples of a state and state setter pair. This is expected to match the same interface as useState in React. The following is a valid simple usage:

const paginator = new Paginator(useState(), useState())

Note that we can also pass the state controllers in via replaceStateControllers rather than in the constructor. This is so we can memoize the Paginator instance which is desirable when using the paginator as a dependency to React hooks.

As state is passed in and managed external to the class be aware that any data stored on the class instance will be lost unless written with setCurrentState or setInternalState. This design is a compromise between allowing a clear interface for how paginators should be defined and allowing the state to be managed externally (eg. using React state).

Arguments:

ArgumentTypeDescription
*currentStatePair[State, ]

The state object and setter (eg. from useState) that is used to store and transition pagination state. Using this you can do things like easily store state in the URL (eg. using useUrlQueryState) or other data sources.

*internalStatePair[State, ]

The state object and setter that is used for internal state. Internal state is stored separately as it does not need to be restored (eg. if you refresh the page). It is used to store things like the total number of results or the current cursor. Passing useState here is fine.

Returns:void
setCurrentState(set)
Source

Changes the current state to the specified value

Arguments:

ArgumentTypeDescription
*set
Returns:void
setInternalState(set)
Source

Changes the internal state to the specified value

Arguments:

ArgumentTypeDescription
*set
Returns:void
setLimit(limit)
Source

Set the limit

Arguments:

ArgumentTypeDescription
*limitnull|number
Returns:void
setOffset(offset)
Source

Arguments:

ArgumentTypeDescription
*offsetnull|number
Returns:void
setResponse(props)
Source

Sets the internal data based on response. Expects limit to be in response data.

See getPaginationState for how to customise this if your backend implementation differs.

Arguments:

ArgumentTypeDescription
*props
Returns:void

Properties

currentState

Source
An object with these properties:
PropertyTypeDescription
limitnumber|string
offsetnumber|string

The current state of the pagination. This is the state that would be serialized (eg. to the URL) and restored when the paginator is created (contrast this to internalState which isn't).

internalState

Source
An object with these properties:
PropertyTypeDescription
responseIsSetboolean
totalnumber|null

The current internal state of the pagination. Internal state refers to state that does not need to be restored (eg. pagination details from the URL for example)

limit

Source
null|number

The current limit

offset

Source
number

The current offset

responseIsSet

Source
boolean

True once setResponse has been called and pagination state is known.

total

Source
null|number

The total number of records available. This will be null before the first response is received.

Static Methods

getPaginationState(requestDetails)
Source

This function is used by paginationMiddleware to extract the state to pass to setResponse from the details returned by Endpoint.execute. For example, if pagination state was stored in response headers this function could extract that into an object that setResponse can then deal with.

If you are using a paginator class directly you can just call setResponse without going via this function.

Each paginator provided by Presto supports a specific request response. If this response differs from your backend you can either extend the pagination class and provide your own or pass the getPaginationState option to paginationMiddleware.

Arguments:

ArgumentTypeDescription
*
requestDetails
An object with the properties below

The value returned by Endpoint.execute

requestDetails.decodedBodyany

The value returned by decodedBody. See Endpoint.execute.

This may be a sub-key of the data returned by Endpoint.execute, eg. if the path option is used in paginationMiddleware. eg. If decodedBody from the Endpoint was

{
    users: {
        count: 10,
        results: [...],
    }
    extraDetails: {...}
}

and paginationMiddleware was used with path: 'users' then decodedBody would be:

{
    count: 10,
    results: [...]
}
requestDetails.queryRecord

Any query string parameters

requestDetails.responseResponse

The Response object, if available

*requestDetails.urlstring

Resolved URL

requestDetails.urlArgsRecord

Any arguments used to resolve URL

Returns:false|Record