DEV Community

dravidjones28
dravidjones28

Posted on

What is React-Query and How to fetch data using react query?

Normally this is how we fetch data from the backend.

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

interface Users {
  id: number;
  name: string;
}

const Users = () => {
  const [users, setUsers] = useState<Users[]>([]);
  const [error, setError] = useState("");

  useEffect(() => {
    axios
      .get("https://jsonplaceholder.typicode.com/users")
      .then((res) => setUsers(res.data))
      .catch((err) => setError(err.message));
  }, []);

  if (error) return <div>{error}</div>;

  return (
    <div>
      {users.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </div>
  );
};

export default Users;

Enter fullscreen mode Exit fullscreen mode

we use useState it allows you to add state to functional components and we use useEffect to fetch data from the backend and store in our state variable.

But there are few problems in this code.

  1. No request cancellation
  2. No separation of concerns
  3. No retries
  4. No automatic refresh
  5. No caching

1.) No request cancellation: we are not cancelling the request if our component is unmounted.

2.) No separation of concerns: the query logic is leaked inside the component, we can't reuse it anywhere.

3.) No retries : we are not retrying failed request.

4.) No automatic refresh: If the data changes, while the users is on this page, they don't see the changes unless they refresh.

5.) No caching: if you want to know what is caching? Caching is the process of storing data in a place where it can be accessed more quickly and efficiently in the future.

We have lots of problem, that's why we use React-query.

React Query is a powerful library for managing data fetching and caching in React applications.

To install react query
On your terminal

npm i @tanstack/react-query

import React from "react";
import ReactDOM from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import App from "./App.tsx";

// We use QueryClient for managing and caching remote data in react query.

// first you need to create a new instance of Query client.
const queryClient = new QueryClient();

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

To fetch data with query hook

we use query hook to fetch the data and give configuration object with two properties
1.) queryKey
2.) queryFn

queryKey -> queryKey is the unique identifier for query, it used for caching, we set this in array of one or more values.

queryFn -> This is the function we use to fetch the data from the backend, this function should return a promise that resolves data or throws an error.

In the body the function I have used axios to fetch the data from the backend.

const userQuery = useQuery({
queryKey: ["users"],
queryFn: axios.get("https://jsonplaceholder.typicode.com/users").then(res => res.data)
})
Enter fullscreen mode Exit fullscreen mode

This userQuery has bunch of properties like data, error, isLoading and so on.

let us destructure the userQuery.

const {data, error, isLoading} = useQuery({
queryKey: ["users"],
queryFn: axios.get("https://jsonplaceholder.typicode.com/users").then(res => res.data)
})
Enter fullscreen mode Exit fullscreen mode

So when calling the query hook, we need to specify the type of errors that might happen when fetching data

const {data, error, isLoading} = useQuery<User[], Error>({
queryKey: ["users"],
queryFn: axios.get("https://jsonplaceholder.typicode.com/users").then(res => res.data)
})
Enter fullscreen mode Exit fullscreen mode
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { useEffect, useState } from "react";

interface Users {
  id: number;
  name: string;
}

const Users = () => {
  const { data, error, isLoading } = useQuery<User[], Error>({
    queryKey: ["users"],
    queryFn: () =>
      axios
        .get<Users[]>("https://jsonplaceholder.typicode.com/users")
        .then((res) => res.data),
  });

if(isLoading) return <div>Loading....!</div>
if(error) return <div>{error.message}</div>

  return (
    <div>
      {data?.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </div>
  );
};

export default Users;
Enter fullscreen mode Exit fullscreen mode

But there is problem in this code, we don't have separation of concerns, our query is leaked.

so create a folder called hooks -> create a file called useUsers.ts

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

interface Users {
  id: number;
  name: string;
}
const useUsers = () =>
  useQuery<Users[], Error>({
    queryKey: ["users"],
    queryFn: () =>
      axios
        .get<Users[]>("https://jsonplaceholder.typicode.com/users")
        .then((res) => res.data),
  });

export default useUsers;

Enter fullscreen mode Exit fullscreen mode
import useUsers from "./hooks/useUsers";

const Users = () => {
  const { data, error, isLoading } = useUsers();

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

  return (
    <div>
      {data?.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </div>
  );
};

export default Users;

Enter fullscreen mode Exit fullscreen mode

Thank you!

Top comments (0)