Skip to content

Commit

Permalink
Merge pull request #9933 from Nilegfx/keep-custom-query-params-in-lis…
Browse files Browse the repository at this point in the history
…t-view

Preserve extra query parameters in List view
  • Loading branch information
slax57 authored Jun 25, 2024
2 parents 0b3f840 + 6011cee commit 9862354
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 14 deletions.
68 changes: 68 additions & 0 deletions packages/ra-core/src/controller/list/useListParams.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useStore } from '../../store/useStore';
import { useListParams, getQuery, getNumberOrDefault } from './useListParams';
import { SORT_DESC, SORT_ASC } from './queryReducer';
import { TestMemoryRouter } from '../../routing';
import { parse } from 'query-string';

describe('useListParams', () => {
describe('getQuery', () => {
Expand Down Expand Up @@ -429,6 +430,73 @@ describe('useListParams', () => {
});
});

it('should synchronize parameters with location and store when sync is enabled while keeping custom query params', async () => {
let locationSearchValue;
let storeValue;
const ComponentThatSetsCustomQueryString = ({
disableSyncWithLocation = false,
}) => {
const [_, { setFilters }] = useListParams({
resource: 'posts',
disableSyncWithLocation,
});

const handleClick = () => {
setFilters({ x: 'y' }, []);
};

return (
<>
<button onClick={handleClick}>set filters</button>
</>
);
};
const StoreReader = () => {
const [value] = useStore('posts.listParams');
React.useEffect(() => {
storeValue = value;
}, [value]);
return null;
};
render(
<TestMemoryRouter
initialEntries={['/posts?foo=bar']}
locationCallback={l => {
locationSearchValue = l.search;
}}
>
<CoreAdminContext dataProvider={testDataProvider()}>
<ComponentThatSetsCustomQueryString />
<StoreReader />
</CoreAdminContext>
</TestMemoryRouter>
);

fireEvent.click(screen.getByText('set filters'));

await waitFor(() => {
expect(parse(locationSearchValue)).toEqual({
displayedFilters: '[]',
filter: '{"x":"y"}',
foo: 'bar',
order: 'ASC',
page: '1',
perPage: '10',
sort: 'id',
});
});

expect(storeValue).toEqual({
displayedFilters: [],
filter: { x: 'y' },
foo: 'bar',
order: 'ASC',
page: 1,
perPage: 10,
sort: 'id',
});
});

test('should not synchronize parameters with location and store when sync is not enabled', async () => {
let location;
let storeValue;
Expand Down
15 changes: 1 addition & 14 deletions packages/ra-core/src/controller/list/useListParams.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useCallback, useMemo, useEffect, useState, useRef } from 'react';
import { parse, stringify } from 'query-string';
import lodashDebounce from 'lodash/debounce';
import pickBy from 'lodash/pickBy';
import { useNavigate, useLocation } from 'react-router-dom';

import { useStore } from '../../store';
Expand Down Expand Up @@ -283,15 +282,6 @@ export const useListParams = ({
];
};

export const validQueryParams = [
'page',
'perPage',
'sort',
'order',
'filter',
'displayedFilters',
];

const parseObject = (query, field) => {
if (query[field] && typeof query[field] === 'string') {
try {
Expand All @@ -303,10 +293,7 @@ const parseObject = (query, field) => {
};

export const parseQueryFromLocation = ({ search }): Partial<ListParams> => {
const query = pickBy(
parse(search),
(v, k) => validQueryParams.indexOf(k) !== -1
);
const query = parse(search);
parseObject(query, 'filter');
parseObject(query, 'displayedFilters');
return query;
Expand Down

0 comments on commit 9862354

Please sign in to comment.