You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The <PrevNextButtons> documentation types storeKey as string | false and describes it as "The key to use to match a filter & sort configuration of a <List>. Pass false to disable."
I expected storeKey={false} to make the pager ignore the stored list params for the resource, so that it pages using only the sort, filter and filterDefaultValues given as props — the same meaning storeKey={false} has on <List>.
The use case: a <Show> view for a message that belongs to a conversation. The prev/next buttons should walk that conversation (filter={{ thread }}, chronological sort) no matter how the user last filtered or sorted the global message list.
What happened instead:
storeKey={false} has no effect — it behaves exactly like omitting the prop. The pager still reads <resource>.listParams from the store, so the list's stored filter is merged into the query and the list's stored sort order overrides the sort prop.
Same page, same props, only storeKey differing:
storeKey={false}
GET /messages?order[displayDate]=desc&page=1&itemsPerPage=1000&direction=outbound&thread=11
storeKey="messages.threadPager" (a key nothing ever writes)
GET /messages?order[displayDate]=asc&page=1&itemsPerPage=1000&thread=11
With storeKey={false} the direction=outbound filter — stored earlier by the list — leaks in, and order=desc from the store wins over the sort={{ field: 'displayDate', order: 'ASC' }} prop.
Steps to reproduce:
Add <PrevNextButtons storeKey={false} sort={{ field: 'last_name', order: 'ASC' }} /> to a <Show> or <Edit> view's actions.
Open the corresponding list and apply a filter and a different sort (e.g. sort by first_name DESC), so params are written to the store.
Open a record's Show/Edit view and watch the getList call the pager issues.
Observed: the call carries the list's stored filter, sorted by first_name DESC. Expected: no filter, sorted by last_name ASC.
Related code:
storeKey is destructured and then used only in the useStore key expression, where false falls through to the default key:
storedParams is then used unconditionally to build the sort and filter passed to getList, so there is no later branch where storeKey === false is honoured — storeKey appears exactly three times in the file: the destructuring, the useStore key, and the type declaration.
Other information:
useListParams has the same storeKey || \${resource}.listParams`expression, but handlesfalseby ignoring the resulting value downstream, with an explicit comment: *"As we can't conditionally call a hook, if the storeKey is false, we'll ignore the params variable later on and won't call setParams either."*usePrevNextController` has no equivalent.
The docs cover this in the props table only; the ## storeKey section documents the string case alone.
Present since <PrevNextButtons> was introduced — the same three lines appear in v4.14.0, v4.16.20, v5.0.0 and current master (4e469da).
Suggested fix, mirroring useListParams: keep calling useStore under the default key (hooks can't be conditional), but ignore storedParams when storeKey === false and fall back to the props-derived defaults. Happy to open a PR if that approach suits you.
Workaround for anyone hitting this: pass a string key that nothing else ever writes (e.g. storeKey="messages.threadPager"), which gives the intended "use only my props" behaviour.
Environment
React-admin version: 5.15.3
Last version that did not exhibit the issue (if applicable): none — present since 4.14.0, the release that introduced the component
React version: 19.3.0
Browser: Chromium 141 (not browser-specific)
Stack trace (in case of a JS error): n/a — no error is raised; the query is silently wrong
What you were expecting:
The
<PrevNextButtons>documentation typesstoreKeyasstring | falseand describes it as "The key to use to match a filter & sort configuration of a<List>. Pass false to disable."I expected
storeKey={false}to make the pager ignore the stored list params for the resource, so that it pages using only thesort,filterandfilterDefaultValuesgiven as props — the same meaningstoreKey={false}has on<List>.The use case: a
<Show>view for a message that belongs to a conversation. The prev/next buttons should walk that conversation (filter={{ thread }}, chronologicalsort) no matter how the user last filtered or sorted the global message list.What happened instead:
storeKey={false}has no effect — it behaves exactly like omitting the prop. The pager still reads<resource>.listParamsfrom the store, so the list's stored filter is merged into the query and the list's stored sort order overrides thesortprop.Same page, same props, only
storeKeydiffering:With
storeKey={false}thedirection=outboundfilter — stored earlier by the list — leaks in, andorder=descfrom the store wins over thesort={{ field: 'displayDate', order: 'ASC' }}prop.Steps to reproduce:
<PrevNextButtons storeKey={false} sort={{ field: 'last_name', order: 'ASC' }} />to a<Show>or<Edit>view's actions.first_name DESC), so params are written to the store.getListcall the pager issues.first_name DESC. Expected: no filter, sorted bylast_name ASC.Related code:
storeKeyis destructured and then used only in theuseStorekey expression, wherefalsefalls through to the default key:react-admin/packages/ra-core/src/controller/usePrevNextController.ts
Lines 133 to 143 in 4e469da
storedParamsis then used unconditionally to build thesortandfilterpassed togetList, so there is no later branch wherestoreKey === falseis honoured —storeKeyappears exactly three times in the file: the destructuring, theuseStorekey, and the type declaration.Other information:
useListParamshas the samestoreKey || \${resource}.listParams`expression, but handlesfalseby ignoring the resulting value downstream, with an explicit comment: *"As we can't conditionally call a hook, if the storeKey is false, we'll ignore the params variable later on and won't call setParams either."*usePrevNextController` has no equivalent.<List storeKey={false}>got its full "disable all store interactions" treatment in Disable all store interactions for a list with storeKey set to false (sort, pagination, filters and now also selection state). #9742. It looks likeusePrevNextControllerwas simply never updated to match.## storeKeysection documents the string case alone.<PrevNextButtons>was introduced — the same three lines appear in v4.14.0, v4.16.20, v5.0.0 and current master (4e469da).useListParams: keep callinguseStoreunder the default key (hooks can't be conditional), but ignorestoredParamswhenstoreKey === falseand fall back to the props-derived defaults. Happy to open a PR if that approach suits you.storeKey="messages.threadPager"), which gives the intended "use only my props" behaviour.Environment