Mastering React Query: A Comprehensive Guide
Tags: react, javascript
Published: 2024-05-22 17:04:34

Tired of juggling Axios and useEffects for API calls and managing dependencies? Say hello to React Query! 🎉 It makes your life easier with automatic caching, synchronization, background updates, and so much more. 🚀

**Traditional Way of API Calling**

In the traditional way, you typically use Axios inside a useEffect hook to make API calls and manage state manually. Here's an example:

```jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios';

const TraditionalAPIComponent = () => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('https://api.example.com/data');
        setData(response.data);
        setIsLoading(false);
      } catch (error) {
        setError(error);
        setIsLoading(false);
      }
    };

    fetchData();
  }, []);

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>Data:</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default TraditionalAPIComponent;
```


## Using React Query (useQuery)

React Query simplifies data fetching by providing hooks that manage caching, synchronization, and background updates out of the box. Here's how you can do the same thing with React Query:

```jsx
import React from 'react';
import { useQuery } from 'react-query';
import axios from 'axios';

const fetchData = async () => {
  const { data } = await axios.get('https://api.example.com/data');
  return data;
};

const ReactQueryComponent = () => {
  const { data, error, isLoading } = useQuery('fetchData', fetchData);

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>Data:</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default ReactQueryComponent;
```

**Adding Dependencies with useQuery**

Sometimes, you need to fetch data based on certain dependencies. In the traditional way, you'd do this with useEffect like so:

```jsx
useEffect(() => {
    // Your fechUserData API call

    fetchUserData(userId);
  }, [userId]);
```

With React Query, you can handle dependencies by using the queryKey and enabled option:

```jsx
const { data, error, isLoading } = useQuery(['userData', userId], () => fetchUserData(userId), {
    enabled: !!userId, // Ensure query is enabled only if userId is truthy
  });
```

**Control Cache Time**

To control cache timing in React Query, you can utilize the cacheTime option within the useQuery hook. This option dictates how long the fetched data remains in the cache before it's considered outdated and possibly removed. Here's how to implement it:

```jsx
const { data, error, isLoading } = useQuery('fetchData', fetchData, {
    cacheTime: 3600000, // Cache data for 1 hour (3600000 milliseconds)
  });
```


## Invalidation with useInvalidateQuery

React Query provides the `useInvalidateQuery` hook to invalidate specific queries. This is useful when you want to refetch data based on certain events, such as user actions or changes in application state.

```jsx
const { data, error, isLoading } = useQuery('fetchData', fetchData);
  const invalidateQuery = useInvalidateQuery('fetchData');

  const handleButtonClick = () => {
    // Invalidates the 'fetchData' query, triggering a refetch
    invalidateQuery();
  };

```



## Using useMutation for update calls

`useMutation` is a hook provided by React Query that simplifies data mutation operations in your React components. It encapsulates common tasks such as making HTTP requests, handling loading and error states, and updating data in response to mutations.

```jsx
const updateUser = async (userData) => {
  const response = await axios.put('https://api.example.com/users', userData);
  return response.data; // Updated user data
};

const [mutate, { isLoading, isError, error, data }] = useMutation(updateUser);

// Execute mutation
const handleUpdateUser = async () => {
  try {
  await mutate({ id: 123, name: 'John Doe', email: 'john@example.com' });
  } catch (error) {
    console.error('An error occurred:', error);
  }
};
```



## Using useInfiniteQuery for paginated API calls

`useInfiniteQuery` is a hook provided by React Query that simplifies pagination operations in your React components. It enables infinite scrolling by fetching data in chunks as the user scrolls, providing a seamless and efficient browsing experience.

```jsx
import React from 'react';
import { useInfiniteQuery } from 'react-query';
import axios from 'axios';

// Define fetch function
const fetchPosts = async ({ pageParam = 1 }) => {
  const response = await axios.get(`https://api.example.com/posts?page=${pageParam}`);
  return response.data;
};

const PostList = () => {
  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isError,
    error,
  } = useInfiniteQuery('posts', fetchPosts, {
    getNextPageParam: (lastPage, allPages) => lastPage.nextPage, // Extract next page number
  });

  return (
    <div>
      {data.pages.map((page, index) => (
        <React.Fragment key={index}>
          {page.posts.map((post) => (
            <div key={post.id}>{post.title}</div>
          ))}
        </React.Fragment>
      ))}
      {isError && <div>Error: {error.message}</div>}
      {hasNextPage && (
        <button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
          {isFetchingNextPage ? 'Loading more...' : 'Load More'}
        </button>
      )}
    </div>
  );
};

export default PostList;

```

**Conclusion**

In wrapping up, React Query's hooks are like magic wands for handling data in React apps! Whether it's fetching data with `useQuery`, updating with `useMutation`, or endless scrolling with `useInfiniteQuery`, React Query simplifies everything. It's the secret sauce that makes building React apps a breeze, freeing you to focus on creating awesome user experiences. So wave goodbye to data headaches and hello to smooth sailing with React Query! ✨🚀