Skip to main content

15.1 - React Query

When working with tRPC on the client side, one of the key tools to know about is React Query. React Query helps manage server state in your React application, making it easier to fetch, cache, and sync data.

What is React Query?

React Query is a powerful library for fetching, caching, and synchronizing server state in React applications. It provides an intuitive API for handling asynchronous operations, such as data fetching and updating, while also managing the cache and background synchronization.

Key Features of React Query

  1. Data Fetching: Easily fetch data from APIs or other sources and handle the result with built-in hooks.
  2. Caching: Automatically cache data to avoid redundant requests and improve performance.
  3. Background Syncing: Automatically refetch data in the background to keep it fresh.
  4. Pagination & Infinite Query: Support for pagination and infinite scrolling to handle large datasets.
  5. Mutations: Simplified handling of creating, updating, and deleting data.
  6. Error Handling: Integrated error handling for failed requests.

How React Query Works

React Query abstracts away much of the complexity involved in managing server state. It provides hooks that interact with a central cache, allowing your components to focus on rendering data rather than managing state or side effects.

Major Tools in React Query

  1. useQuery: Fetches data and manages loading, error, and data states.
  2. useMutation: Handles creating, updating, or deleting data.
  3. useQueryClient: Provides access to the React Query client for manual cache management and invalidation.

React Query in Action

Fetching Data with useQuery

The useQuery hook is used to fetch data from an API or other data source. Here’s an example of how to use it with tRPC:

// src/hooks/useUser.ts
import { useQuery } from "react-query";
import { trpc } from "../utils/trpc";

export const useUser = (id: string) => {
return useQuery(["user", id], () => trpc.user.getUser.query({ id }));
};

In this example:

  • useQuery takes two arguments: a unique query key (['user', id]) and a function to fetch the data.
  • trpc.user.getUser.query is used to call a tRPC procedure.
note

Query Keys

Query keys are used to uniquely identify a query and its data in the cache. They are essential for:

  • Fetching Data: React Query uses the query key to fetch and cache data.
  • Invalidating Data: The key helps to target specific queries when invalidating the cache.
  • Refetching Data: React Query can refetch data based on the query key.

Handling Mutations with useMutation

The useMutation hook is used for creating, updating, or deleting data. Here’s an example:

// src/hooks/useUpdateUser.ts
import { useMutation } from "react-query";
import { trpc } from "../utils/trpc";

export const useUpdateUser = () => {
return useMutation((userData: { id: string; name: string }) =>
trpc.user.updateUser.mutate(userData)
);
};

In this example:

  • useMutation takes a function that performs the mutation (e.g., trpc.user.updateUser.mutate).
  • You can handle success, error, and loading states using the returned object.

Manual Cache Management with useQueryClient

Sometimes, you may need to manually invalidate or update the cache. Here’s how to use useQueryClient:

// src/hooks/useInvalidateUserCache.ts
import { useQueryClient } from "react-query";

export const useInvalidateUserCache = () => {
const queryClient = useQueryClient();

return (id: string) => {
queryClient.invalidateQueries(["user", id]);
};
};

In this example:

  • useQueryClient provides access to the React Query client.
  • invalidateQueries is used to manually invalidate and refetch data for a specific query key.
note

Invalidating Stale Data

Invalidating stale data ensures that React Query refetches data to reflect the latest state from the server. This is especially useful for ensuring consistency after a mutation or when specific data may have changed.