Data fetching with React Query && Axios

Data fetching with React Query && Axios

Hi Again , In this blog post , we are going to use react query to fetch data from server.

we will be using dummy json api to get random data.

Let's go.

First of all , let's take a look at our folders/files architecture :

You can find the source code on Github :

https://github.com/chikno/whitebeard-dev/tree/data-fetching-using-react-query

Install dependencies

I have a huge preference for pnpm , but you can use whatever Package Manager you are comfortable with.


pnpm add axios @tanstack/react-query

Create the API provider

create a file api-provider.tsx in your app and fill it with this content


import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import * as React from 'react';

export const queryClient = new QueryClient();

export function APIProvider({ children }: { children: React.ReactNode }) {
  return (
    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  );
}

the next step is to wrap our app component with the query client provider.

Open main.tsx file and update it like this

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { APIProvider } from './common/api-provider';
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <APIProvider>
      <App />
    </APIProvider>
  </React.StrictMode>
);

Create the Axios Client

Let's create our axios client once . then we will use it to send every request to the API. it will prevents us to write each time the request options.

create a file called : client.js , then put this code on it


import axios from 'axios';
export const client = axios.create({
  baseURL: "https://dummyjson.com/"
});

Service Type

Create a service type to safely insure that we send and get the correct data through our api calls.

Create a file called types.ts inside a types folder.

export type Service = {
    id: number;
    title: string;
    body: string
    tags:[];
  };

Implement the custom hook to fetch data

Create a file called use-services.ts

import type { AxiosError , AxiosResponse} from "axios";
import { createQuery } from "react-query-kit";

import { client } from "../common/client";
import type { Service } from "../types/types";

type Response = Service[];
type Variables = undefined;

export const useServices = createQuery<Response, Variables, AxiosError>({
  queryKey: ["services"],
  fetcher: () => {
    return client.get(`/posts`).then((response: AxiosResponse<Response>) => response.data?.posts);
  },
});

now that we have our data fetcher, let's display this in our front end.

what is awesome with those react query hooks , is that they provide every step of the data feching ; from loading ,to error , and the data if success.

Let's call our hook now in the page we wish to display the services list.

import './App.css'
import { useServices } from './hooks/use-services';
import type { Service } from './types/types';
function App() {
  const { data, isLoading, isError } = useServices();

  const renderItem = (service:Service, index:number) => {
    return (
      <div key={index} className='flex flex-col items-center justify-between'>
        <h3 className='font-bold text-xl'  >{service.title}</h3>
        <p>{service.body}</p>
      </div>
    )
  }

  if (isLoading) {
    return <div className='flex-1'>Loading...</div>
  }

  if (isError) {
    return <div className='flex-1'>An error occured</div>
  }

  return (
    <div className='flex-1'>
      {data && data.map((service:Service, index:number) => {
        return renderItem(service, index)
      })}
    </div>
  )
}

export default App

first , we call destructure thet request state from the use-services hooks .

   const { data, isLoading, isError } = useServices();

if we are still waiting for the server , we can display some skeleton or some loading message.

  if (isLoading) {
    return <div className='flex-1'>Loading...</div>
  }

if the server returns an error , we can display an error message.

  if (isError) {
    return <div className='flex-1'>An error occured</div>
  }

otherwise , we loop throught the services then display each item

  return (
    <div className='flex-1'>
      {data && data.map((service:Service, index:number) => {
        return renderItem(service, index)
      })}
    </div>
  )

That's it.
Happy coding and if you find this article usefull or if you have a better idea fetch data from the server , dont forget to leave a comment so we can discuss it .

Happy coding.