My API provides cursor-based pagination not offset-limit pagination, so is hard to match up to the page: {int}
and perPage: {int}
configuration that React-Admin provides for GET_LIST
and GET_MANY_REFERENCE
.
Cursor-based pagination is used by many APIs with fast-moving data like Twitter, Facebook and Slack.
At its simplest cursor-based pagination means that a list response includes (either in response body or headers) opaque cursors that are 'bookmarks' to the end of the previous page and beginning of the next page. It may or not include cursors for every resource in the response, and may or not include persistent cursors for the first and last available pages. A cursor-based paginated API may well also not be able to provide a meaningful 'total count' of the resources matching the provided filter, as currently insisted upon in the react-admin GET_LIST
and GET_MANY_REFERENCE
responses.
Similar questions seem to have been asked on React-Admin issue tracker (react-admin#1510 and react-admin#1787) and on Stack-Overflow How to paginate react-admin lists when the total is unknown?) but all the answers seem to be quite fragile workarounds.
To be specific about the request/response idiom supported by my API, an initial request might be like so:
GET http://example.com/api/resources?<filter-params>&paging.limit=10
The response includes up to the requested 10 resources, and cursors that mark the beginning and end of this page:
X-Paging-Since: <since-cursor>
X-Paging-Until: <until-cursor>
[ {...}, {...}, ... ]
The previous page is then:
GET http://example.com/api/resources?<filter-params>&paging.until=<since-cursor>
and the next page is:
GET http://example.com/api/resources?<filter-params>&paging.since=<until-cursor>
(In this API, those complete URLs for next/prev (and first/last) are actually available in the Link response headers also:
Link: <prev-url>;rel=prev, <next-url>;rel=next, <first-url>;rel=first, <last-url>;rel=last
.)
Obviously my data provider could reformat these headers into the data returned to react-admin however we want, but it's not clear how best to wire up to the react-admin List
or Pagination
components, or the Pagination
component to pass the appropriate cursor/URL back to the data provider for the next request.
dataProvider
after the initialGET_LIST
, pass the paging parameters through to the data response. Use a custom reducer as described in https://mcmap.net/q/1918978/-how-to-paginate-react-admin-lists-when-the-total-is-unknown to store the paging position in redux. On your next GET_LIST call, grab the paging results out of redux and format them to your API. This isn't fragile as it uses react-admin's existing redux system, stores state where it should be stored – Stealthyif (type == CRUD_GET_LIST_SUCCESS) { return payload.lastid } else if (type == CRUD_GET_LIST) { if (previousState !== null ) { payload.pagination['lastid'] = previousState }}
. My problem is, the previous pages aren't cached. For example, when I click prev, another call is made to getList which ends up using the previous the lastid and pages forward. I'll continue investigating and update this as I go. – Coterminous