1

I'm trying to write a custom hook that uses useQuery from react-query. The custom hook takes in the id of an employee and fetches some data and returns it to the consuming component. I want to be able to dispatch a redux action to show a loading indicator or show an error message if it fails. Here is my custom hook.

export default function useEmployee(id) {
  const initial = {
    name: '',
    address: '',
  }

  const query = useQuery(['fetchEmployee', id], () => getEmployee(id), {
    initialData: initial,
    onSettled: () => dispatch(clearWaiting()),
    onError: (err) => dispatch(showError(err)),
  })
  if (query.isFetching || query.isLoading) {
    dispatch(setWaiting())
  }
  return query.data
}

When I refresh the page, I get this error in the browser's console and I'm not sure how to fix this error?

Warning: Cannot update a component (`WaitIndicator`) while rendering a different component (`About`). 
To locate the bad setState() call inside `About`, follow the stack trace as described in

1 Answer 1

2

The issue is likely with dispatching the setWaiting action outside any component lifecycle, i.e. useEffect. Move the dispatch logic into a useEffect hook with appropriate dependency.

Example:

export default function useEmployee(id) {
  const initial = {
    name: '',
    address: '',
  };

  const { data, isFetching, isLoading } = useQuery(['fetchEmployee', id], () => getEmployee(id), {
    initialData: initial,
    onSettled: () => dispatch(clearWaiting()),
    onError: (err) => dispatch(showError(err)),
  });

  useEffect(() => {
    if (isFetching || isLoading) {
      dispatch(setWaiting());
    }
  }, [isFetching, isLoading]);
  
  return data;
}
Sign up to request clarification or add additional context in comments.

4 Comments

while this answer is correct in answering the question, the question itself is a bit weird. Why would you want to do that? It does seem like an anti-pattern to me to sync loading states from react-query to redux to show loading spinners...
@TkDodo It doesn't seem that odd to me at all to sync any loading state into app state if there're possibly other components that necessarily need to know the loading state of fetched data. If OP was using redux-toolkit/query with an API slice instead of react-query, would storing/tracking the loading status be anti-pattern in your opinion then? It's effectively the same thing but the coupling of query statuses and app state is already handled.
I just meant that react-query already make the loading state of queries globally available, so if other components need it, they can access it. useIsFetching would be one way for example.
@TkDodo Ah, I see. Admittedly I'm not very familiar with react-query specifics.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.