I have two useState
state values currently, and they rely on each other. Here’s some pseudocode:
[getId, setId] = useState();
[getSearchParam1, setSearchParam1] = useSearchParams();
useEffect(() => {
setId(getSearchParam1)
}, [getSearchParam1])
useEffect(() => {
setSearchParam1(getId)
}, [getId])
where searchParam1
is just "www.google.com?searchParam1=xyz"
. The idea is that the searchParam
and the id
should always be the same value, but searchParam
is a nullable value and id
is either set to ''
or an actual id. This code does work most of the time fine, but when I hit the back button on my browser, because searchParam
changes, for some reason the useEffect
hooks are activated simultaneously and constantly try to update each other’s values. This causes the useEffect
s to constantly fire, reloading the page forever until I refresh. Is there any way to avoid this from happening?
So far I’ve tried to set an isLoading
state to prematurely break out of the useEffect
s, but that doesn’t seem like the best way to resolve the issue. There’s probably a better way I’m not thinking of.
The recommendation is to always have exhaustive hooks, so I don’t want to just remove the dependencies in the useEffect
, but I’m not sure what else to do.
2
Answers
Your best bet is to combine both effects and compare the values:
Note: Convention-wise, the first value in the
useState
destructuring call is not a getter, it’s a value, so the "get" prefix is confusing and incorrect.But a better way to do this would be to eliminate the
id
state and just stick with thesearchParam1
param fromuseSearchParams
.It is a bit of a React anti-pattern to duplicate passed state/props values into local state. In this case the
searchParams
value is the actual source of truth, there’s no need to over-complicate things by duplicating the search params values into local state and need to add a bunch of additional logic to synchronize the local state to the search params and search params to the local state. Just use thesearchParams
directly.Use a callback handler to update the search params directly instead of messing the duplicate state and trying to synchronize. This effects a navigation change to the current route path but with updated search string, and the component will rerender and pick up the updated
"searchParam1"
value.Example: