React Query Hooks

ยท 376 words ยท 2 minute read

React Query is arguably the most popular library for React. I’m going to show how I typically use it with a simple example.

Take this custom hook as an example, in the file userQueryActiveUsers.ts:

export function useQueryActiveUsers({
  countries,
  disabled,
}: {
  countries: string[];
  disabled?: boolean;
}): {
  users?: UsersResponse[];
  isLoading: boolean;
} {
  const { addToast } = useToast();

  const { data, error, isLoading } = useQuery<UsersResponse[], Error>(
    [CACHE_KEY.users({ countries })],
    API.users.get({ countries }),
    {
      enabled: !disabled && !!countries.length,
      staleTime: 1 * 60 * 60 * 1000,
    }
  );

  useEffect(() => {
    if (!error || !addToast) {
      return;
    }

    addErrorToast("Error retrieving users");
  }, [error, addToast]);

  const users = data.users.filter((user) => user.active);

  return { users, isLoading };
}

Abstracting Call Details ๐Ÿ”—

The central idea of the hook is to abstract components from the details of the call. In this sense, the data consumer can omit logic that would otherwise be repeated every time the call is made, such as the use of the react-query library and the actual call to execute.

Caching ๐Ÿ”—

There are two mechanisms at play when establishing caching. On one hand, there’s the key used to store the data:

[CACHE_KEY.users({ countries })];

CACHE_KEY is an object that contains the definitions of the functions responsible for constructing the keys for the cache.

On the other hand, caching time is defined:

staleTime: 1 * 60 * 60 * 1000,

In this case, React Query is instructed to keep the call in the cache for one hour.

Response Processing ๐Ÿ”—

In addition to abstracting the call logic, we can use the hook to transform the response we get from the server. In this case, we filter the users to only return those who are active. We could improve the implementation, if needed, by including a new parameter in the hook that decides whether to filter or not.

Error Handling ๐Ÿ”—

We can take the opportunity to define a common behavior in case of an error. In this case, upon detecting an error in the call, a toast message is shown to the user for notification. There are other ways to implement error handling more efficiently, such as centralizing logic on the client and detecting an error in any call. However, the mechanism presented here is sufficient for most cases.