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
PaginationItem
component appears to close over a stale copy of the search params and it doesn't appear as though you can "intercept" theLink
component'sonClick
event handler to manually handle the search params because it's thePaginationItem
component's click handler that it needs to effect the page change.Best suggestion I can think of is to use the
Pagination
component'sonChange
handler to synchronize the URL search params to the changed page value.Example:
If you must use a
Link
component as the pagination item then it would seem the issue is trying to spread thesearchParams
object into a newURLSearchParams
object, it doesn't correctly shallow copy the search parameters. Move the logic of computing a new search string outside theto
prop.Example: