react-router: [Bug]: Make setSearchParams stable?
What version of React Router are you using?
6.7.0
Steps to Reproduce
- Use
setSearchParamsin anything that needs a dependency array and add it to avoid issues. - Notice that the presence of
setSearchParamsin the dependency array triggers the useEffect any time the searchParams change (for example) to run again
Expected Behavior
I expect to be able to use setSearchParams in a useEffect and not have that useEffect re-run just because search params changed.
Actual Behavior
This is happening because setSearchParams allows you to pass a function callback which receives the current searchParams so setSearchParams changes whenever the searchParams change. This is a nice API, but leads to unexpected re-runs of things using setSearchParams.
An alternative is to use a ref to keep track of the latest searchParams and pass that ref.current instead so searchParams doesn’t need to be listed in the nextInit call. I can’t think of a scenario where this would break anything.
The code I’m talking about is here:
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 44
- Comments: 21 (2 by maintainers)
I feel that all functions in hooks, especially those we’ll call in other hooks or as props to a component, are supposed to be stable. we just need to be able to get the latest states when these functions are called.
The following is a simple solution to create stable functions:
What is the progress on this? Will the fix be merged?
Currently I see two issues with
setSearchParams.flushSyncbut that is a waste of renders.Setters are usually imperative, not reactive. That is why React’s
useStateis a stable function and it allows us to pass a callback to ensure we are working with the latest data.I ran into this same issue today - and since it was causing React rendering errors in the console, I decided to go ahead and put together a fix: https://github.com/remix-run/react-router/pull/10740
Also, if multiple updates happen in the same render cycle, using the new value as a dependency of the callback causes it to no be provided within the prev param of the n+1
setSearchParamscallAlso, calling
setSearchParamswill re-render the whole route. It would be very helpful if at least there would be some sort of flag on each route config, similar toshouldRevalidate, that let’s you opt out of such re-renders.any update? or does anyone know of an alternative to
react-routerwhich has a stable solution?Thank you! Hope to see this merged soon!
I ran into the issue today, absolutely unexpected and seems very dangerous.
@lucabergamini yes