Dispatch actions from a custom hook using useQuery

Viewed 30

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 Answers

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;
}
Related