diff --git a/docs/PrevNextButtons.md b/docs/PrevNextButtons.md index f7e782c5b38..1066b29c981 100644 --- a/docs/PrevNextButtons.md +++ b/docs/PrevNextButtons.md @@ -301,7 +301,9 @@ export const MyAdmin = () => ( `` can get the current list parameters (sort and filters) from the store. This prop is useful if you specified a custom `storeKey` for a `` and you want `` to use the same stored parameters. -See [`storeKey` in ``](./List.md#storekey) for more information. +If you don't want `` to read the parameters stored by the `` (for instance, to let users browse a thread of messages from a `` view regardless of how they last filtered the messages list), pass `false`: the pager will then rely only on its own `sort`, `filter` and `filterDefaultValues` props. + +See [`storeKey` in ``](./List.md#storekey) for more information. ```tsx export const MyAdmin = () => ( diff --git a/packages/ra-core/src/controller/usePrevNextController.ts b/packages/ra-core/src/controller/usePrevNextController.ts index 29149df0d47..483e10111a5 100644 --- a/packages/ra-core/src/controller/usePrevNextController.ts +++ b/packages/ra-core/src/controller/usePrevNextController.ts @@ -130,26 +130,31 @@ export const usePrevNextController = ( ); } + const defaultParams: ListParams = { + filter: filterDefaultValues, + order: initialSort.order, + sort: initialSort.field, + page: 1, + perPage: 10, + displayedFilters: {}, + }; + // As we can't conditionally call a hook, if the storeKey is false, + // we'll ignore the storedParams variable later on and use the + // props-derived defaults instead. const [storedParams] = useStore( storeKey || `${resource}.listParams`, - { - filter: filterDefaultValues, - order: initialSort.order, - sort: initialSort.field, - page: 1, - perPage: 10, - displayedFilters: {}, - } + defaultParams ); + const listParams = storeKey === false ? defaultParams : storedParams; const dataProvider = useDataProvider(); const queryClient = useQueryClient(); const pagination = { page: 1, perPage: limit }; const sort = { - field: storedParams.sort, - order: storedParams.order, + field: listParams.sort, + order: listParams.order, }; - const filter = { ...storedParams.filter, ...permanentFilter }; + const filter = { ...listParams.filter, ...permanentFilter }; const { meta, ...otherQueryOptions } = queryOptions; const params = { pagination, sort, filter, meta }; @@ -163,8 +168,8 @@ export const usePrevNextController = ( { ...params, pagination: { - page: storedParams.page, - perPage: storedParams.perPage, + page: listParams.page, + perPage: listParams.perPage, }, }, ]); @@ -172,11 +177,11 @@ export const usePrevNextController = ( r => r.id === record?.id ); const isRecordIndexFirstInNonFirstPage = - recordIndexInQueryData === 0 && storedParams.page > 1; + recordIndexInQueryData === 0 && listParams.page > 1; const isRecordIndexLastInNonLastPage = queryData?.data && queryData?.total ? recordIndexInQueryData === queryData?.data?.length - 1 && - storedParams.page < queryData?.total / storedParams.perPage + listParams.page < queryData?.total / listParams.perPage : undefined; const canUseCacheData = record && @@ -249,8 +254,7 @@ export const usePrevNextController = ( ? undefined : index + (canUseCacheData - ? (storedParams.perPage ?? 0) * - ((storedParams.page ?? 1) - 1) + ? (listParams.perPage ?? 0) * ((listParams.page ?? 1) - 1) : 0), total: canUseCacheData ? queryData?.total : data?.total, error, diff --git a/packages/ra-ui-materialui/src/button/PrevNextButtons.spec.tsx b/packages/ra-ui-materialui/src/button/PrevNextButtons.spec.tsx index 176882440d6..77e9f3bad59 100644 --- a/packages/ra-ui-materialui/src/button/PrevNextButtons.spec.tsx +++ b/packages/ra-ui-materialui/src/button/PrevNextButtons.spec.tsx @@ -9,6 +9,7 @@ import { WithFilter, WithLimit, WithQueryFilter, + WithoutStoreKey, } from './PrevNextButtons.stories'; describe('', () => { @@ -109,6 +110,43 @@ describe('', () => { }); }); + describe('storeKey', () => { + it('should ignore the stored list params when storeKey is false', async () => { + const data = { + customers: Array.from(Array(900).keys()).map(id => { + const first_name = `first_name_${id}`; + const last_name = `last_name_${id}`; + const email = `first_name_${id}.last_name_${id}@example.com`; + + return { + id, + first_name, + last_name, + email, + city: `city_${Math.floor(id / 50)}`, + }; + }), + }; + const dataProvider = fakeRestDataProvider(data); + const spy = jest.spyOn(dataProvider, 'getList'); + render(); + const input = await screen.findByLabelText('Search'); + fireEvent.change(input, { target: { value: 'city_0' } }); + await screen.findByText('1-10 of 50'); + const item = await screen.findByText('first_name_9'); + fireEvent.click(item); + await screen.findByRole('navigation'); + await screen.findByText('11 / 900'); + expect(spy).toHaveBeenCalledWith('customers', { + pagination: { page: 1, perPage: 1000 }, + sort: { field: 'first_name', order: 'DESC' }, + filter: {}, + meta: undefined, + signal: undefined, + }); + }); + }); + describe('limit', () => { it('should render the total number of items, even with a limit', async () => { render(); diff --git a/packages/ra-ui-materialui/src/button/PrevNextButtons.stories.tsx b/packages/ra-ui-materialui/src/button/PrevNextButtons.stories.tsx index bf33081d380..965697869b6 100644 --- a/packages/ra-ui-materialui/src/button/PrevNextButtons.stories.tsx +++ b/packages/ra-ui-materialui/src/button/PrevNextButtons.stories.tsx @@ -156,6 +156,66 @@ export const WithStoreKey = () => ( ); +export const WithoutStoreKey = ({ customDataProvider = dataProvider }: any) => ( + + + + , + ]} + /> + } + edit={ + + + + + } + /> + } + show={ + + + + + } + /> + } + /> + + + +); + export const WithFilter = () => (