-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Add pagination to NewChatPage #88452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6d23e93
5cf743f
003e26f
7fc615a
8d30a5e
1801324
6286eeb
c21b360
a48299e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| import {useState} from 'react'; | ||
|
|
||
| type UsePaginatedDataConfig = { | ||
| /** When this value changes, pagination resets to the first page. */ | ||
| resetKey?: string; | ||
|
|
||
| /** When true, returns `data` as-is with `hasMore: false` and a no-op `loadMore`. */ | ||
| skipPagination?: boolean; | ||
| }; | ||
|
|
||
| /** | ||
| * Client-side bounded-slice pagination. | ||
| * | ||
| * Returns the first `pageSize * currentPage` items of `data`, plus `loadMore` to advance a page and | ||
| * `hasMore` to indicate whether more items are available. `currentPage` is reset to 1 whenever | ||
| * `resetKey` changes, so callers can tie the page back to a logical context (e.g. a search query). | ||
| */ | ||
| function usePaginatedData<T>( | ||
| data: T[], | ||
| pageSize: number, | ||
| {resetKey = '', skipPagination = false}: UsePaginatedDataConfig = {}, | ||
| ): { | ||
| paginatedData: T[]; | ||
| loadMore: () => void; | ||
| hasMore: boolean; | ||
| } { | ||
| const [prevResetKey, setPrevResetKey] = useState(resetKey); | ||
| const [currentPage, setCurrentPage] = useState(1); | ||
|
|
||
| if (resetKey !== prevResetKey) { | ||
| setPrevResetKey(resetKey); | ||
| setCurrentPage(1); | ||
| } | ||
|
|
||
| if (skipPagination) { | ||
| return {paginatedData: data, loadMore: () => {}, hasMore: false}; | ||
| } | ||
|
|
||
| if (pageSize < 1) { | ||
| return {paginatedData: [], loadMore: () => {}, hasMore: false}; | ||
| } | ||
|
Comment on lines
+35
to
+41
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could these early returns can go above the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. at first, after reading this question, I though it would be better to move it down. But actually it needs to stay in place. Example: If we move the condition down, the change in resetKey would go unnoticed; the pagination would not reset to the first page. |
||
|
|
||
| const limit = pageSize * currentPage; | ||
| const paginatedData = data.slice(0, limit); | ||
| const hasMore = data.length > limit; | ||
|
sharabai marked this conversation as resolved.
|
||
|
|
||
| const loadMore = () => { | ||
| if (!hasMore) { | ||
| return; | ||
| } | ||
| setCurrentPage((prev) => prev + 1); | ||
| }; | ||
|
|
||
| return {paginatedData, loadMore, hasMore}; | ||
| } | ||
|
|
||
| export default usePaginatedData; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
resetKeychanges after the user has already loaded multiple pages, this hook queuessetCurrentPage(1)but still computeslimitfrom the previouscurrentPagein the same render. That means one render returns too many rows for the new context (for example, after changing the search term), which can briefly show stale pagination and trigger extraonEndReachedwork before the next render corrects it.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you call the set function during render, React will re-render that component immediately after your component exits with a return statement, and before rendering the children.