I want to navigate to the same route, but preserve all search params on link click and change only the page.
I am using Material-UI's Pagination component and React-Router-DOM's Link.
I have tried spreading the existng search params and changing only the page, but it removes all params and appends only the page one.
import Divider from '@mui/material/Divider';
import Box from '@mui/material/Box';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import Pagination from '@mui/material/Pagination';
import { useDataQuery } from '../../api';
import { itemsPerPage } from '../../constants';
import { PaginationItem } from '@mui/material';
import {
Link,
createSearchParams,
useLocation,
useSearchParams
} from 'react-router-dom';
export function PaginatedList() {
const { data } = useDataQuery();
const [searchParams, setSearchParams] = useSearchParams();
const location = useLocation();
const currentPage = Number(searchParams.get('page')) || 1;
const pageCount = data?.total ? Math.ceil(data?.total / itemsPerPage) : 1;
return (
<Box>
<List>
{data.items.map((dataItem) => (
<ListItem key={dataItem.id}>
<Card item={dataItem} />
</ListItem>
))}
</List>
<Divider />
<Box>
<Pagination
defaultPage={1}
page={currentPage}
count={pageCount}
renderItem={(item) => (
<PaginationItem
component={Link}
to={{
pathname: location.pathname,
search:
item.page === 1
? ''
: createSearchParams({
...searchParams,
page: item.page?.toString(),
}).toString(),
}}
{...item}
/>
)}
/>
</Box>
</Box>
);
}
I have also tried setting the query like this, but it does not seem to do anything (it is not appending any params to the pathname):
to={{
pathname: location.pathname,
query: {
...searchParams,
page: item.page,
},
}}
Here is the link to the working codesandbox demo.
The
PaginationItemcomponent appears to close over a stale copy of the search params and it doesn't appear as though you can "intercept" theLinkcomponent'sonClickevent handler to manually handle the search params because it's thePaginationItemcomponent's click handler that it needs to effect the page change.Best suggestion I can think of is to use the
Paginationcomponent'sonChangehandler to synchronize the URL search params to the changed page value.Example:
If you must use a
Linkcomponent as the pagination item then it would seem the issue is trying to spread thesearchParamsobject into a newURLSearchParamsobject, it doesn't correctly shallow copy the search parameters. Move the logic of computing a new search string outside thetoprop.Example: