Skip to content

Commit 1c0ce2d

Browse files
authoredFeb 27, 2024··
feat: pagination row count apis, new pagination docs (#5377)
* feat: pagination row count apis, new pagination docs * same version of react query in every example * merge main * upgrade faker
1 parent 8004b9a commit 1c0ce2d

File tree

48 files changed

+524
-320
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+524
-320
lines changed
 

‎docs/api/features/pagination.md

+25-9
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,15 @@ Enables manual pagination. If this option is set to `true`, the table will not a
3838
pageCount?: number
3939
```
4040
41-
When manually controlling pagination, you should supply a total `pageCount` value to the table if you know it. If you do not know how many pages there are, you can set this to `-1`.
41+
When manually controlling pagination, you can supply a total `pageCount` value to the table if you know it. If you do not know how many pages there are, you can set this to `-1`. Alternatively, you can provide a `rowCount` value and the table will calculate the `pageCount` internally.
42+
43+
### `rowCount`
44+
45+
```tsx
46+
rowCount?: number
47+
```
48+
49+
When manually controlling pagination, you can supply a total `rowCount` value to the table if you know it. `pageCount` will be calculated internally from `rowCount` and `pageSize`.
4250
4351
### `autoResetPageIndex`
4452
@@ -118,14 +126,6 @@ resetPageSize: (defaultState?: boolean) => void
118126
119127
Resets the page size to its initial state. If `defaultState` is `true`, the page size will be reset to `10` regardless of initial state.
120128
121-
### `setPageCount`
122-
123-
```tsx
124-
setPageCount: (updater: Updater<number>) => void
125-
```
126-
127-
Updates the page count using the provided function or value.
128-
129129
### `getPageOptions`
130130
131131
```tsx
@@ -166,6 +166,22 @@ nextPage: () => void
166166
167167
Increments the page index by one, if possible.
168168
169+
### `firstPage`
170+
171+
```tsx
172+
firstPage: () => void
173+
```
174+
175+
Sets the page index to `0`.
176+
177+
### `lastPage`
178+
179+
```tsx
180+
lastPage: () => void
181+
```
182+
183+
Sets the page index to the last available page.
184+
169185
### `getPageCount`
170186
171187
```tsx

‎docs/guide/pagination.md

+205-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ title: Pagination Guide
77
Want to skip to the implementation? Check out these examples:
88

99
- [pagination](../framework/react/examples/pagination)
10-
- [pagination-controlled](../framework/react/examples/pagination-controlled)
10+
- [pagination-controlled (React Query)](../framework/react/examples/pagination-controlled)
1111
- [editable-data](../framework/react/examples/editable-data)
1212
- [expanding](../framework/react/examples/expanding)
1313
- [filters](../framework/react/examples/filters)
@@ -18,4 +18,207 @@ Want to skip to the implementation? Check out these examples:
1818

1919
[Pagination API](../api/features/pagination)
2020

21-
## Pagination Guide
21+
## Pagination Guide
22+
23+
TanStack Table has great support for both client-side and server-side pagination. This guide will walk you through the different ways to implement pagination in your table.
24+
25+
### Client-Side Pagination
26+
27+
Using client-side pagination means that the `data` that you fetch will contain ***ALL*** of the rows for the table, and the table instance will handle pagination logic in the front-end.
28+
29+
#### Should You Use Client-Side Pagination?
30+
31+
Client-side pagination is usually the simplest way to implement pagination when using TanStack Table, but it might not be practical for very large datasets.
32+
33+
However, a lot of people underestimate just how much data can be handled client-side. If your table will only ever have a few thousand rows or less, client-side pagination can still be a viable option. TanStack Table is designed to scale up to 10s of thousands of rows with decent performance for pagination, filtering, sorting, and grouping. The [official pagination example](../framework/react/examples/pagination) loads 100,000 rows and still performs well, albeit with only handful of columns.
34+
35+
Every use-case is different and will depend on the complexity of the table, how many columns you have, how large every piece of data is, etc. The main bottlenecks to pay attention to are:
36+
37+
1. Can your server query all of the data in a reasonable amount of time (and cost)?
38+
2. What is the total size of the fetch? (This might not scale as badly as you think if you don't have many columns.)
39+
3. Is the client's browser using too much memory if all of the data is loaded at once?
40+
41+
If you're not sure, you can always start with client-side pagination and then switch to server-side pagination in the future as your data grows.
42+
43+
#### Should You Use Virtualization Instead?
44+
45+
Alternatively, instead of paginating the data, you can render all rows of a large dataset on the same page, but only use the browser's resources to render the rows that are visible in the viewport. This strategy is often called "virtualization" or "windowing". TanStack offers a virtualization library called [TanStack Virtual](https://tanstack.com/virtual/latest) that can work well with TanStack Table. The UI/UX of both virtualization and pagination have their own trade-offs, so see which one works best for your use-case.
46+
47+
#### Pagination Row Model
48+
49+
If you want to take advantage of the built-in client-side pagination in TanStack Table, you first need to pass in the pagination row model.
50+
51+
```jsx
52+
import { useReactTable, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table';
53+
//...
54+
const table = useReactTable({
55+
columns,
56+
data,
57+
getCoreRowModel: getCoreRowModel(),
58+
getPaginationRowModel: getPaginationRowModel(), //load client-side pagination code
59+
});
60+
```
61+
62+
### Manual Server-Side Pagination
63+
64+
If you decide that you need to use server-side pagination, here is how you can implement it.
65+
66+
No pagination row model is needed for server-side pagination, but if you have provided it for other tables that do need it in a shared component, you can still turn off the client-side pagination by setting the `manualPagination` option to `true`. Setting to the `manualPagination` option to `true` will tell the table instance to use the `table.getPrePaginationRowModel` row model under the hood, and it will make the table instance assume that the `data` that you pass in is already paginated.
67+
68+
#### Page Count and Row Count
69+
70+
Also, the table instance will have no way of knowing how many rows/pages there are in total in your back-end unless you tell it. Provide either the `rowCount` or `pageCount` table option to let the table instance know how many pages there are in total. If you provide a `rowCount`, the table instance will calculate the `pageCount` internally from `rowCount` and `pageSize`. Otherwise, you can directly provide the `pageCount` if you already have it. If you don't know the page count, you can just pass in `-1` for the `pageCount`, but the `getCanNextPage` and `getCanPreviousPage` row model functions will always return `true` in this case.
71+
72+
```jsx
73+
import { useReactTable, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table';
74+
//...
75+
const table = useReactTable({
76+
columns,
77+
data,
78+
getCoreRowModel: getCoreRowModel(),
79+
// getPaginationRowModel: getPaginationRowModel(), //not needed for server-side pagination
80+
manualPagination: true, //turn off client-side pagination
81+
rowCount: dataQuery.data?.rowCount, //pass in the total row count so the table knows how many pages there are (pageCount calculated internally if not provided)
82+
// pageCount: dataQuery.data?.pageCount, //alternatively directly pass in pageCount instead of rowCount
83+
});
84+
```
85+
86+
> **Note**: Setting the `manualPagination` option to `true` will make the table instance assume that the `data` that you pass in is already paginated.
87+
88+
### Pagination State
89+
90+
Whether or not you are using client-side or manual server-side pagination, you can use the built-in `pagination` state state and APIs.
91+
92+
The `pagination` state is an object that contains the following properties:
93+
94+
- `pageIndex`: The current page index (zero-based).
95+
- `pageSize`: The current page size.
96+
97+
You can manage the `pagination` state just like any other state in the table instance.
98+
99+
```jsx
100+
import { useReactTable, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table';
101+
//...
102+
const [pagination, setPagination] = useState({
103+
pageIndex: 0, //initial page index
104+
pageSize: 10, //default page size
105+
});
106+
107+
const table = useReactTable({
108+
columns,
109+
data,
110+
getCoreRowModel: getCoreRowModel(),
111+
getPaginationRowModel: getPaginationRowModel(),
112+
onPaginationChange: setPagination, //update the pagination state when internal APIs mutate the pagination state
113+
state: {
114+
//...
115+
pagination,
116+
},
117+
});
118+
```
119+
120+
Alternatively, if you have no need for managing the `pagination` state in your own scope, but you need to set different initial values for the `pageIndex` and `pageSize`, you can use the `initialState` option.
121+
122+
```jsx
123+
const table = useReactTable({
124+
columns,
125+
data,
126+
getCoreRowModel: getCoreRowModel(),
127+
getPaginationRowModel: getPaginationRowModel(),
128+
initialState: {
129+
pagination: {
130+
pageIndex: 2, //custom initial page index
131+
pageSize: 25, //custom default page size
132+
},
133+
},
134+
});
135+
```
136+
137+
> **Note**: Do NOT pass the `pagination` state to both the `state` and `initialState` options. `state` will overwrite `initialState`. Only use one or the other.
138+
139+
### Pagination Options
140+
141+
Besides the `manualPagination`, `pageCount`, and `rowCount` options which are useful for manual server-side pagination (and discussed [above](#manual-server-side-pagination)), there is one other table option that is useful to understand.
142+
143+
#### Auto Reset Page Index
144+
145+
The `autoResetPageIndex` table option is true by default, and it will reset the `pageIndex` to `0` when page-altering state changes occur, such as when the `data` is updated, filters change, grouping changes, etc. This is useful to prevent the table from showing an empty page when the `pageIndex` is out of range.
146+
147+
However, you can opt out of this behavior by setting the `autoResetPageIndex` option to `false`.
148+
149+
```jsx
150+
const table = useReactTable({
151+
columns,
152+
data,
153+
getCoreRowModel: getCoreRowModel(),
154+
getPaginationRowModel: getPaginationRowModel(),
155+
autoResetPageIndex: false, //turn off auto reset of pageIndex
156+
});
157+
```
158+
159+
Be aware, however, that if you turn off `autoResetPageIndex`, you may need to add some logic to handle resetting the `pageIndex` yourself to avoid showing empty pages.
160+
161+
### Pagination APIs
162+
163+
There are several pagination table instance APIs that are useful for hooking up your pagination UI components.
164+
165+
#### Pagination Button APIs
166+
167+
- `getCanPreviousPage`: Useful for disabling the "previous page" button when on the first page.
168+
- `getCanNextPage`: Useful for disabling the "next page" button when there are no more pages.
169+
- `previousPage`: Useful for going to the previous page. (Button click handler)
170+
- `nextPage`: Useful for going to the next page. (Button click handler)
171+
- `firstPage`: Useful for going to the first page. (Button click handler)
172+
- `lastPage`: Useful for going to the last page. (Button click handler)
173+
- `setPageIndex`: uUseful for a "go to page" input.
174+
- `resetPageIndex`: Useful for resetting the table state to the original page index.
175+
- `setPageSize`: Useful for a "page size" input/select
176+
- `resetPageSize`: Useful for resetting the table state to the original page size.
177+
- `setPagination`: Useful for setting all of the pagination state at once.
178+
- `resetPagination`: Useful for resetting the table state to the original pagination state.
179+
180+
> **Note**: Some of these APIs are new in `v8.13.0`
181+
182+
```jsx
183+
<Button
184+
onClick={() => table.firstPage()}
185+
disabled={!table.getCanPreviousPage()}
186+
>
187+
{'<<'}
188+
</Button>
189+
<Button
190+
onClick={() => table.previousPage()}
191+
disabled={!table.getCanPreviousPage()}
192+
>
193+
{'<'}
194+
</Button>
195+
<Button
196+
onClick={() => table.nextPage()}
197+
disabled={!table.getCanNextPage()}
198+
>
199+
{'>'}
200+
</Button>
201+
<Button
202+
onClick={() => table.lastPage()}
203+
disabled={!table.getCanNextPage()}
204+
>
205+
{'>>'}
206+
</Button>
207+
<select
208+
value={table.getState().pagination.pageSize}
209+
onChange={e => {
210+
table.setPageSize(Number(e.target.value))
211+
}}
212+
>
213+
{[10, 20, 30, 40, 50].map(pageSize => (
214+
<option key={pageSize} value={pageSize}>
215+
{pageSize}
216+
</option>
217+
))}
218+
</select>
219+
```
220+
221+
#### Pagination Info APIs
222+
223+
- `getPageCount`: Useful for showing the total number of pages.
224+
- `getRowCount`: Useful for showing the total number of rows.

0 commit comments

Comments
 (0)
Please sign in to comment.