useInfiniteList
useInfiniteList
is a modified version of react-query
's useInfiniteQuery
used for retrieving items from a resource
with pagination, sort, and filter configurations. It is ideal for lists where the total number of records is unknown and the user loads the next pages with a button.
It uses the getList
method as the query function from the dataProvider
which is passed to <Refine>
.
Usage
Let's assume that we have a posts
resource with the following data:
{
[
{
id: 1,
title: "E-business",
status: "draft",
},
{
id: 2,
title: "Virtual Invoice Avon",
status: "published",
},
{
id: 3,
title: "Powerful Crypto",
status: "rejected",
},
];
}
First of all, we will use useInfiniteList
without passing any query configurations.
import { useInfiniteList } from "@pankod/refine-core";
type IPost = {
id: number;
title: string;
status: "rejected" | "published" | "draft";
};
const postInfiniteListResult = useInfiniteList<IPost>({ resource: "posts" });
{
"status": "success",
"data": {
"pages": [
{
"data": [
{
"id": 1,
"title": "E-business",
"status": "draft"
},
{
"id": 2,
"title": "Virtual Invoice Avon",
"status": "published"
}
],
"total": 1370
}
]
},
"hasNextPage": true,
"hasPreviousPage": false,
"isFetchingNextPage": false,
"isFetchingPreviousPage": false
...
}
If your API returns the result like above, you can use useInfiniteList without any configuration.
getList
also has default values for pagination:
{
pagination: { current: 1, pageSize: 10 }
}
If you want to create your own getList
method, it will automatically implement default query configurations since useInfiniteList
can work with no configuration parameters.
Query Configuration
pagination
Allows us to set page and items per page values.
For example imagine that we have 1000 post records:
import { useInfiniteList } from "@pankod/refine-core";
const postListQueryResult = useInfiniteList({
resource: "posts",
config: {
pagination: { current: 3, pageSize: 8 },
},
});
sort
Allows us to sort records by the speficified order and field.
import { useInfiniteList } from "@pankod/refine-core";
const postListQueryResult = useInfiniteList<IPost>({
resource: "posts",
config: {
sort: [{ order: "asc", field: "title" }],
},
});
filters
Allows us to filter queries using refine's filter operators. It is configured via field
, operator
and value
properites.
Refer to supported operators. →
import { useInfiniteList } from "@pankod/refine-core";
const postListQueryResult = useInfiniteList<IPost>({
resource: "posts",
config: {
filters: [
{
field: "status",
operator: "eq",
value: "rejected",
},
],
},
});
useInfiniteList
returns the result of react-query
's useInfiniteQuery
which includes many properties such as fetchNextPage
, hasNextPage
and isFetchingNextPage
.
- For example, to disable query from running automatically you can set
enabled
tofalse
.
import { useInfiniteList } from "@pankod/refine-core";
const postListQueryResult = useInfiniteList<IPost>({
resource: "posts",
queryOptions: {
enabled: false,
getNextPageParam: ({ data }) => {
const lastRow = data[data.length - 1];
return lastRow.id;
},
},
});
API
Properties
Config parameters
interface UseListConfig {
hasPagination?: boolean;
pagination?: {
current?: number;
pageSize?: number;
};
sort?: Array<{
field: string;
order: "asc" | "desc";
}>;
filters?: Array<{
field: string;
operator: CrudOperators;
value: any;
}>;
}
Type Parameters
Property | Desription | Type | Default |
---|---|---|---|
TData | Result data of the query. Extends BaseRecord | BaseRecord | BaseRecord |
TError | Custom error object that extends HttpError | HttpError | HttpError |
Return values
Description | Type |
---|---|
Result of the react-query 's useInfiniteQuery | InfiniteQueryObserverResult<{ data: TData[]; total: number; }, TError> |
FAQ
How to use cursor based pagination?
Some APIs use the cursor-pagination
method for its benefits. This method uses a cursor
object to determine the next set of data. The cursor can be a number or a string and is passed to the API as a query parameter.
Preparing the data provider:
Consumes data from data provider useInfiniteList
with getList
method. First of all, we need to make the this method in the data provider convenient for this API. The cursor
data is kept in pagination
and should be set to 0
by default.
getList: async ({ resource, pagination }) => {
const { current } = pagination;
const { data } = await axios.get(
`https://api.fake-rest.refine.dev/${resource}?cursor=${current || 0}`,
);
return {
data: data[resource],
total: 0,
};
},
As the total
data is only needed in the offset-pagination
method, define it as 0
here.
After this process, we have successfully retrieved the first page data. Let's fill the cursor
object for the next page.
getList: async ({ resource, pagination }) => {
const { current } = pagination;
const { data } = await axios.get(
`https://api.fake-rest.refine.dev/${resource}?cursor=${current || 0}`,
);
return {
data: data[resource],
total: 0,
cursor: {
next: data.cursor.next,
prev: data.cursor.prev,
},
};
},
How to override the getNextPageParam
method?
By default, refine
expects you to return the cursor
object, but is not required. This is because some APIs don't work that way. To fix this problem you need to override the getNextPageParam
method and return the next cursor
.
import { useInfiniteList } from "@pankod/refine-core";
const {
data,
error,
hasNextPage,
isLoading,
fetchNextPage,
isFetchingNextPage,
} = useInfiniteList({
resource: "posts",
queryOptions: {
getNextPageParam: (lastPage, allPages) => {
// return the last post's id
const { data } = lastPage;
const lastPost = data[data.length - 1];
return lastPost.id;
},
},
});
When you override this method, you can access the lastPage
and allPages
.