-
-
Notifications
You must be signed in to change notification settings - Fork 36
Description
Problems and use-cases
Problems
Pagination and infinite scroll are common queries used a lot and mostly need a typical units for storing page, next parameters and etc. So This API will solve these problems make work with queries such types easier.
'Cause this PR is big, I split it on two parts. This one is about pagination. The second will be after this.
Use cases
Common use-case it's flow where the page is identified by a number and the next(previous) also can be requested with page number, not link received from server. Pagination by server sent link may be classified as edge-case, 'cause it's not very popular, but sometimes used.
Analysis, pros, cons and pitfalls
Analysis
I researched several libs/packages provided queries and looked at their pagination receipts.
The first group contains SWR, @tanstack/query and RTK-Query. All them don't provide special methods for pagination. It makes queries more flexible, but more times makes us write the same code.
If try to find a reason for such decisions, I can guess that SWR and @tanstack/query were designed so for integration with view frameworks and managing from them.
The second group now contains only effector-pagination. This lib implement pagination fabric using effector units. This fabric manage current page, possibility to make request and caching. I think main pros it's encapsulation of change page logic and predicates of possibility fetch next and prev page.
Suggested implementation, compatibility with others APIs
I suggest to make pagination as extended type of Query. This will allow us to integrate pagination with keepFresh, retry and cache without much problems, 'cause it will be query with some extra fields and methods.
Interface may look like:
interface Pagination<Params extends RequiredPageParams, Data, Error, InitialData = null> extends Query<Params, Data, Error, InitialData> {
$page: Store<number>;
$hasNext: Store<boolean>;
$hasPrev: Store<boolean>;
next: Event<void>;
prev: Event<void>;
specific: Event<RequiredPageParams>;
}And using like that:
import { createPagination } from "@farfetched/core";
const pagination = createPagination(...)
pagination.start({ ..., page: 1 }) // Request 1th page
pagination.next() // Request 2th page
pagination.prev() // Request 1th page again
pagination.specific({ page: 43 }) // Request 43th pageRestrictions
- Params of passed handler/effect should extend RequiredPageParams interface which provides requested page and limit of requested items.
- How to determine the end of pagination? We may restrict shape of mapData response and make this function required.
Function may return object like this:
interface MapDataShape<Data> {
data: Data;
currentPage: number;
hasNextPage: boolean;
// Or change field on totalPages: number;
hasPrevPage: boolean;
}And then this object will be split filed to store.
- Base params(params passed into start method) will be used for next requests(next, prev, specific) with overriding page prop. But if user want to change one of it(even offset) he will need to call start method again. Base params will be got from $latestParams. Also user can't to fetch next and others pagination method if there're not $latestParams
- This implementation doesn't support pagination depended on server sent links at all. But cover the most popular cases with number pagination.
Pagination now
The first written in official example of farfetched and provide query with some stores for storing pages.
I've not found any more.