Endre Szabó
Endre Szabó

Reputation: 584

Correct way to change router state

I have a router state "refetch" that triggers the component to refetch its data (instead of using the cached one), but when it's done, I'd like to toggle that state back to avoid an infinite loop. What is the best way to change state parameters? Or this approach is wrong?

const { state } = useLocation<{ refetch: boolean }>()
  
const query = useQuery<....>()
    
useEffect(() => {
  if (state.refetch) {
    query.refetch()
    state.refetch = false // feels wrong to me
  }
}, [query, state])

Upvotes: 1

Views: 277

Answers (2)

devraulu
devraulu

Reputation: 36

If you're using React Query, you don't need to add an useEffect for that, you can add dependencies to a query, passing an array as the query key, eg:

useQuery(['key', ...dependencies], queryFn);

Every time the dependencies change it will refetch the query.

In your case you could try useQuery(['key', state], queryFn);

If you need to stick to the refetch of the history, you could add the toggle to the queryFn

Query Keys - React Query

If your function depends on a variable include it in your query key - Stack Overflow

PD: You shouldn't use an object or array as a dependency for useEffect or useMemo, etc. That will always cause an infinite loop. You could stringify them first using JSON.stringify(foo), use a property of the object, maybe the length of the array. Personally, I stringify them, that way the comparison is more accurate.

Upvotes: 1

Drew Reese
Drew Reese

Reputation: 203322

I think instead of mutating the route state object you could issue a redirect with the refetch state set false.

Example:

const history = useHistory();
const { pathname, state } = useLocation();
  
const query = useQuery<....>();
    
useEffect(() => {
  if (state.refetch) {
    query.refetch();
    history.replace(pathname, { refetch: false });
  }
}, [query, state]);

Upvotes: 1

Related Questions