react-router
react-router copied to clipboard
[Docs]: for useSearchParams, functional updates should be explained in more detail
Describe what's incorrect/missing in the documentation
Looking at https://reactrouter.com/en/main/hooks/use-search-params, one may think that to update one param while keeping the others, one can do:
const [searchParams, setSearchParams] = useSearchParams()
//...
const setPageNumber = (pageNumber: number) => setSearchParams(params => ({ ...params, page: String(pageNumber) }))
to update just the page portion of the query. However, this doesn't work: it removes all the query params and sets just the page portion. (not sure if this is a bug or an intended behavior)
To work around this, one has to do:
const setPageNumber = (pageNumber: number) => setSearchParams(params => {
params.set('page', String(pageNumber))
return params
})
I think this is not trivial, and hence should be documented (unless it's a bug, I'm using 6.22.3).
URLSearchParams is not a regular object, so you can't spread it like you normally would.
Instead, you need to convert the existing params into an object via Object.fromEntries()
const [searchParams, setSearchParams] = useSearchParams()
//...
const setPageNumber = (pageNumber: number) =>
setSearchParams(params => ({ ...Object.fromEntries(params), page: String(pageNumber) }))
https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams
IMHO the bigger undocumented caveat is that any mutation of searchParams (the first array entry returned), e.g. searchParams.delete('page') has the side effect of actually changing the URL.
Yeah, both are relevant: the Object.fromEntries trick would be helpful there, and then an explanation of how to properly delete a param would be also useful. Is
setSearchParams(params => {
const queryParams = Object.fromEntries(params)
delete queryParams['page']
return queryParams
})
sufficient to avoid side-effects?
Just a warning: Object.fromEntries will return an incomplete copy if the URLSearchParams contains array values (e.g. ?a=4&a=5 will be collapsed to {a: 5}. Check the MDN link from earlier in the thread for how to use .entries() of the URLSearchParams instead, though in the case of a simple deletion this is cleaner:
const newParams = new URLSearchParams(params)
newParams.delete('page')
return newParams
IMHO the bigger undocumented caveat is that any mutation of
searchParams(the first array entry returned), e.g.searchParams.delete('page')has the side effect of actually changing the URL.
This is a huge omission, and your comment here is what allowed me to solve a bug in my app that was having me tear out my remaining hair.