https://github.com/mitodl/course-search-utils/compare/cc/useSearchParams-bug?expand=1
Expected Behavior
setSearchParams(current => next) should always update the search params and should use the current value.
Current Behavior
Separate instances of setSearchParams overwrite each other for updates within the same render.
Steps to Reproduce
See the (failing) test added in https://github.com/mitodl/course-search-utils/compare/cc/useSearchParams-bug?expand=1#diff-57f641eeee56cf15d2f3647e24ee973979cc56e0dc15566cbda0db31ed9da952R143
Additional Details
Fixing this may not be a high priority. We have a workaround. But I wanted to leave notes for our future selves.
React Query's [searchParams, setSearchParams] = useSearchParams() hook is advertised as being similar to React's builtin [state, setState] = useState() hook, but using the router's search parameters as the state.
However, a major caveat is that multiple updates within the same render cycle do not use current value of search parameters:
setSearchParams("?a=1")
setSearchParams(current => {
const copy = new URLSearchParams(current)
copy.set("b", 2)
return copy
})
// Expected: `?a=1&b=2`
// Actual: `?b=2
See
course-search-utils makes heavy use of setting search params, and it's useful to be able to set the parameters independently in different locations. As such, course-search-utils exports a wrapped version of useSearchParams that addresses this issue.
However, separate instances of our custom useSearchParams still exhibit this behavior:
import { useSearchParams } from "@mitodl/course-search-utils/react-router"
const [_, setSearchParams1] = useSearchParams()
const [_, setSearchParams2] = useSearchParams()
// then later
setSearchParams1(current => {/* append parameter a= 1 */})
setSearchParams2(current => {/* append parameter a= 2 */})
// results in only the latest update
To be clear, both updates occur correctly if there's only one occurrence of useSearchParams.
See https://github.com/mitodl/course-search-utils/compare/cc/useSearchParams-bug?expand=1#diff-57f641eeee56cf15d2f3647e24ee973979cc56e0dc15566cbda0db31ed9da952R143 for a test demonstrating this issue
Concrete example and Workaround
A concrete example of this occurring was in mitodl/mit-learn#1132, where two separate callbacks were fired on the same click, one updating page=1 and the other updating resource_type.
Workaround: Pass the same setSearchParam setter from parent rather than accessing via hook.
Possible Solution
Our wrapped useSearchParam stores the current search params in a ref. That ref could be put in a context, so separate "instances" of the hook share it.
https://github.com/mitodl/course-search-utils/compare/cc/useSearchParams-bug?expand=1
Expected Behavior
setSearchParams(current => next)should always update the search params and should use the current value.Current Behavior
Separate instances of
setSearchParamsoverwrite each other for updates within the same render.Steps to Reproduce
See the (failing) test added in https://github.com/mitodl/course-search-utils/compare/cc/useSearchParams-bug?expand=1#diff-57f641eeee56cf15d2f3647e24ee973979cc56e0dc15566cbda0db31ed9da952R143
Additional Details
Fixing this may not be a high priority. We have a workaround. But I wanted to leave notes for our future selves.
React Query's
[searchParams, setSearchParams] = useSearchParams()hook is advertised as being similar to React's builtin[state, setState] = useState()hook, but using the router's search parameters as the state.However, a major caveat is that multiple updates within the same render cycle do not use current value of search parameters:
See
for further discussion of this issue.
course-search-utilsmakes heavy use of setting search params, and it's useful to be able to set the parameters independently in different locations. As such, course-search-utils exports a wrapped version ofuseSearchParamsthat addresses this issue.However, separate instances of our custom
useSearchParamsstill exhibit this behavior:To be clear, both updates occur correctly if there's only one occurrence of useSearchParams.
See https://github.com/mitodl/course-search-utils/compare/cc/useSearchParams-bug?expand=1#diff-57f641eeee56cf15d2f3647e24ee973979cc56e0dc15566cbda0db31ed9da952R143 for a test demonstrating this issue
Concrete example and Workaround
A concrete example of this occurring was in mitodl/mit-learn#1132, where two separate callbacks were fired on the same click, one updating
page=1and the other updatingresource_type.Workaround: Pass the same
setSearchParamsetter from parent rather than accessing via hook.Possible Solution
Our wrapped
useSearchParamstores the current search params in a ref. That ref could be put in a context, so separate "instances" of the hook share it.