DEV Community

Cover image for Master React API Management with TanStack React Query: Best Practices & Examples
Mofajjal Rasul
Mofajjal Rasul

Posted on • Edited on

1

Master React API Management with TanStack React Query: Best Practices & Examples

The TanStack React Query library simplifies API state management in React applications, offering a robust and highly configurable toolkit for handling asynchronous data fetching and caching. In this article, we explore how to set up and utilize React Query effectively, focusing on useQuery and useMutation hooks with examples of practical usage.


Setting Up React Query

Query Client Configuration

The QueryClient serves as the core of React Query, allowing you to define global behaviors for queries. Below is a setup with custom defaults for error handling and query behaviors.

import { QueryClient, QueryFunctionContext } from "@tanstack/react-query";
import axios from "axios";
import BASE_URL from "./apiEndpoint";

const apiInstance = axios.create({
  baseURL: BASE_URL,
});

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      queryFn: async ({ queryKey, signal }: QueryFunctionContext) => {
        const { data } = await apiInstance(`${queryKey[0]}`, { signal });
        return data;
      },
    },
  },
});

export default apiInstance;
Enter fullscreen mode Exit fullscreen mode

Integrating React Query with Your App

Wrap your root component with the QueryClientProvider to provide the QueryClient context to your application.

import ReactDOM from "react-dom/client";
import { QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "./lib/api/queryClient";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

Leveraging React Query Hooks

Fetching Data with useQuery

The useQuery hook provides a straightforward way to fetch and cache data. Here’s an example of fetching a list of items:

import { useQuery } from "@tanstack/react-query";

const ItemsList = () => {
  const { data, isLoading, isError } = useQuery({ queryKey: ["/items"] });

  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error loading items.</div>;

  return (
    <ul>
      {data.map((item: { id: number; name: string }) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
};

export default ItemsList;
Enter fullscreen mode Exit fullscreen mode

Mutating Data with useApiMutation

Mutations handle data modifications such as creating, updating, or deleting resources. Here’s how you can implement a reusable mutation hook.

import { useMutation, UseMutationResult } from "@tanstack/react-query";
import { AxiosError } from "axios";
import apiInstance from "../lib/api/queryClient";

interface MutationHookOptions<TData, TVariables> {
  endpoint: string;
  method?: "POST" | "PUT" | "DELETE";
  isMultiPart?: boolean;
}

function useApiMutation<TData = unknown, TVariables = unknown>({
  endpoint,
  method = "POST",
  isMultiPart = false,
}: MutationHookOptions<TData, TVariables>): UseMutationResult<TData, AxiosError, TVariables> {
  const mutationFn = async (variables: TVariables) => {
    const response = await apiInstance.request<TData>({
      url: endpoint,
      method,
      data: variables,
      headers: {
        "Content-Type": isMultiPart ? "multipart/form-data" : "application/json",
      },
    });
    return response.data;
  };

  return useMutation(mutationFn);
}

export default useApiMutation;
Enter fullscreen mode Exit fullscreen mode

Examples of useApiMutation Usage

Create a New Item

const CreateItem = () => {
  const mutation = useApiMutation({
    endpoint: "/items",
    method: "POST",
  });

  const handleSubmit = () => {
    mutation.mutate({ name: "New Item" }, {
      onSuccess: () => alert("Item created!"),
    });
  };

  return <button onClick={handleSubmit}>Create Item</button>;
};
Enter fullscreen mode Exit fullscreen mode

Update an Existing Item

const UpdateItem = ({ id }: { id: number }) => {
  const mutation = useApiMutation({
    endpoint: `/items/${id}`,
    method: "PUT",
  });

  const handleUpdate = () => {
    mutation.mutate({ name: "Updated Item" }, {
      onSuccess: () => alert("Item updated!"),
    });
  };

  return <button onClick={handleUpdate}>Update Item</button>;
};
Enter fullscreen mode Exit fullscreen mode

Delete an Item

const DeleteItem = ({ id }: { id: number }) => {
  const mutation = useApiMutation({
    endpoint: `/items/${id}`,
    method: "DELETE",
  });

  const handleDelete = () => {
    mutation.mutate(undefined, {
      onSuccess: () => alert("Item deleted!"),
    });
  };

  return <button onClick={handleDelete}>Delete Item</button>;
};
Enter fullscreen mode Exit fullscreen mode

Conclusion

React Query significantly reduces boilerplate and simplifies API interactions in React applications. With features like caching, query invalidation, and mutation management, it ensures optimal performance and a seamless developer experience. By configuring a QueryClient and utilizing hooks like useQuery and useMutation, you can efficiently manage API calls with minimal effort.

Start implementing these patterns today and supercharge your React application's API handling!

Billboard image

Imagine monitoring that's actually built for developers

Join Vercel, CrowdStrike, and thousands of other teams that trust Checkly to streamline monitor creation and configuration with Monitoring as Code.

Start Monitoring

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay