payload icon indicating copy to clipboard operation
payload copied to clipboard

ListDrawer Per-Page Dropdown Always Resets to 10 Instead of Using Saved Limit

Open sbhattarai-xm opened this issue 4 months ago • 0 comments

Describe the Bug

We're using ListDrawer (via useListDrawer) and noticed odd behavior with the “per page” value:

  • The first time the drawer opens → the per-page dropdown shows the default 10.
  • If we change it to 5, the new value is stored in the preferences database.
  • But when we close and reopen the drawer → it shows 10 again, even though the data is fetched using our saved preference.

This means the server uses the correct limit, but the UI does not show it.

Root Cause (Step by Step)

  1. ListDrawerContent calls a server function with name = 'render-list'.
  2. That runs renderListView(), which fetches data and passes it to DefaultListView.
  3. DefaultListView uses <PageControls />.

PageControls Behavior

Inside PageControls, from source code

<PageControlsComponent
  ...
  limit={isNumber(query.limit) ? query.limit : initialLimit}
/>
  • query.limit is undefined in ListDrawer (unlike full collection pages, it doesn’t use URL query params).
  • initialLimit is also undefined the first time.
  • Therefore, limit passed down is undefined.

What PageControlsComponent Does

Source Code

limit (which is undefined) is forwarded to <PerPage />.

PerPage Behavior

const limitToUse = isNumber(limit) ? limit : defaultLimit;

Since limit is undefined → it falls back to (source code):

defaultLimit = 10

This is why the dropdown always resets to 10, even though the backend correctly uses the saved preference (data.limit).

Why This Works in Normal Collection Tables but Not in ListDrawer?

  • Collection pages do set the limit query param.
  • The server uses that limit and sends it back.
  • UI sees query.limit and everything stays consistent.

But ListDrawer:

  • Does not use query params.
  • So query.limit is always undefined.
  • UI falls back to 10 every time.

Proposed Fix

Pass the effective limit from the backend whenever the query-based one is missing.

For example:

limit={query.limit || data.limit}

And use the same value for both:

  • Pagination
  • PerPage dropdown

This ensures the UI shows the correct per-page value (from preferences) even when the list is rendered using useListDrawer hook.

Link to the code that reproduces this issue

https://github.com/payloadcms/payload

Reproduction Steps

1. Open a ListDrawer that uses useListDrawer()

  • Trigger any ListDrawer in your app that relies on the hook.
  • Observe that the “Per Page” dropdown shows 10 (the default).

2. Change the "Per page" value

  • Change the dropdown from 10 → 5.

  • Confirm that:

    • The list reloads using limit = 5.
    • The preference is saved to the database (verify via DB or reload behavior).

3. Close the ListDrawer

  • Exit the drawer completely.

4. Re-open the same ListDrawer

  • Observe the “Per page” dropdown again.

Actual result:

  • The dropdown resets to 10, even though the backend is returning considering limit = 5.

Expected result:

  • The dropdown should show 5, matching the saved preference and backend data.

Which area(s) are affected? (Select all that apply)

area: ui

Environment Info

Binaries:
  Node: 22.19.0
  npm: 10.9.3
  Yarn: 1.22.22
  pnpm: 10.23.0
Relevant Packages:
  payload: 3.60.0
  next: 15.4.4
  @payloadcms/db-mongodb: 3.60.0
  @payloadcms/graphql: 3.60.0
  @payloadcms/next/utilities: 3.60.0
  @payloadcms/richtext-lexical: 3.60.0
  @payloadcms/translations: 3.60.0
  @payloadcms/ui/shared: 3.60.0
  react: 19.1.0
  react-dom: 19.1.0
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 24.6.0: Wed Oct 15 21:09:41 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T8122
  Available memory (MB): 24576
  Available CPU cores: 8

sbhattarai-xm avatar Nov 28 '25 12:11 sbhattarai-xm