DEV Community

Manas
Manas

Posted on

Why do you need react query ?

Hello everyone, this is Manas here.
How do you fetch data when using React?
Simple question, right? You might think to just do:

  const response = await fetch(url);
  const data = response.json();
  console.log(data);
Enter fullscreen mode Exit fullscreen mode

But what if there is no data at the URL, or an error occurs? Taking it one step further, you get something like this:

import React, { useEffect, useState } from "react";

function DataFetcher() {
  const [data, setData] = useState(null);     // stores fetched data
  const [loading, setLoading] = useState(true); // indicates loading state
  const [error, setError] = useState(null);     // stores error message

  useEffect(() => {
    async function fetchData() {
      try {
        setLoading(true);
        setError(null);

        const response = await fetch("https://jsonplaceholder.typicode.com/posts");

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchData();
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error) return <p style={{ color: "red" }}>Error: {error}</p>;

  return (
    <div>
      <h2>Fetched Data:</h2>
      <ul>
        {data.slice(0, 5).map((item) => (
          <li key={item.id}>
            <strong>{item.title}</strong>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default DataFetcher;
Enter fullscreen mode Exit fullscreen mode

This may seem simple if you're just starting with React and are in the honeymoon phase of learning, but as your application grows and the number of components increases, managing error, data, and loading states becomes a headache. Also, what if different components request the same data? This adds request overhead on the server for the same data.
First, you should know that React Query is a server-state management library. But what is server state? It:

a) Is persisted remotely in a location you may not control or own.
b) Requires asynchronous APIs for fetching and updating.
c) Implies shared ownership and can be changed by others without your knowledge.
d) Can potentially become "out of date" in your application if you're not careful.

What React Query helps you with:

1.Caching (possibly the hardest thing to do in programming).
2.Deduping multiple requests for the same data into a single request.
3.Updating "out of date" data in the background.
4.Knowing when data is "out of date."
5.Reflecting updates to data as quickly as possible.
6.Providing loading and error states, etc.

Without React Query, you would have to write custom functions to keep checking when data changes, to cache data, and to update it.
Enough talk—let's dive into the fundamentals of React Query.
(Here, I won’t talk about wrapping the app in QueryClientProvider, etc. You can refer to their docs for that. We will focus on the main things you need to start with.)
Here’s how a basic snippet of fetching data looks:

function Example() {
  const { isPending, error, data } = useQuery({
    queryKey: ['repoData'],
    queryFn: async () => {
    const response = await fetch('/todos/' + todoId)
    if (!response.ok) {
      throw new Error('Network response was not ok')
    }
    return response.json()
  },
  })

  if (isPending) return 'Loading...'

  if (error) return 'An error has occurred: ' + error.message

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.description}</p>
      <strong>👀 {data.subscribers_count}</strong>{' '}
      <strong> {data.stargazers_count}</strong>{' '}
      <strong>🍴 {data.forks_count}</strong>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

You may see unfamiliar syntax—don’t worry, we’ll go through each line one by one to understand it.

1.Query: What does a query mean? It is a declarative dependency on an asynchronous source of data tied to a unique key (sounds overwhelming, right?). In simple terms, when you search for “cute cat videos” on YouTube, your search is a query. For any data resource you subscribe to, it’s a query using a query key.

2.Query Key: React Query manages caching and fetching using query keys. These are unique identifiers that help you associate data with a query. For example, in the above example, the query key is repoData, which means if another query uses the same key, it will get the same data from the cache (if not stale). This way, you avoid multiple requests for the same data.
The simplest form of keys is an array, but it can be more complex, like:

An individual todo:

useQuery({ queryKey: ['todo', 5], ... })
Enter fullscreen mode Exit fullscreen mode

An individual todo in a "preview" format:

useQuery({ queryKey: ['todo', 5, { preview: true }], ... })
Enter fullscreen mode Exit fullscreen mode

A list of todos that are "done":

useQuery({ queryKey: ['todos', { type: 'done' }], ... })
Enter fullscreen mode Exit fullscreen mode

3.Query Functions: React Query doesn’t have its own functions; instead, it uses native functions like fetch or libraries such as Axios.

4.States: Every query has states to track the status of the query. These are:
a) isPending or status === 'pending': The query has no data yet.
b) isError or status === 'error': The query encountered an error.
c) isSuccess or status === 'success': The query was successful, and data is available.

Beyond these primary states, more information is available depending on the state of the query:
a) error: If the query is in an isError state, the error is available via the error property.
b) data: If the query is in an isSuccess state, the data is available via the data property.
Using these, you can display data, error messages, or loading components without needing to manage these states yourself.
That’s it for this blog. Thank you for reading, and if you want to learn more, check out the TanStack Query docs: Link
Additional resources: Why did we add a throw block in fetch? Because fetch does not reject promises on error responses ,link to article -Link

Top comments (0)