React: Axios hook with typescript

Axios is great library for data fetching, having over 17M+ monthly downloads, lets create a custom hook for our react app.

What we need?

  • State
  • Axios function to call.

Let's start writing our code, first declare a generic function hook useAxios

const useAxios = <T extends {}>() => {}

Now our state part

  const [data, setData] = React.useState<T>();
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState({});

See I have used <T> which means our state will be same as type T

const loadData = React.useCallback(
    async (
      endpoint: string,
      body?: any,
      config?: AxiosRequestConfig,
      method: "get" | "post" | "delete" | "patch" = "get"
    ) => {
      setLoading(true);
      await axios[method]<T>(endpoint, body, config)
        .then((res) => {
          setData(res.data);
          setLoading(false);
        })
        .catch((err) => {
          setError(err);
          setLoading(false);
        });
    },
    []
  );

This would be our function which will call the axios, axios[method] will call any one of method from get, post, patch, delete. Now return all the data

 return { data, loading, error, loadData };

Now let's define our expected response type

type ResponseType = {
  userId: number;
  id: number;
  title: string;
  body: string;
};

and let's write our react component

export const MyComponent = (): JSX.Element => {
  const { data, error, loadData, loading } = useAxios<ResponseType>();

  React.useEffect(() => {
    loadData("https://jsonplaceholder.typicode.com/posts/1");
  }, []);

  return (
    <div>
      {loading && "Loading..."}
      {data && (
        <div>
          {data.title}
          {data.userId}
        </div>
      )}
      {error && JSON.stringify(error)}
    </div>
  );
};

So whole code would look like

import React from "react";
import axios, { AxiosRequestConfig } from "axios";

const useAxios = <T extends {}>() => {
  const [data, setData] = React.useState<T>();
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState({});

  const loadData = React.useCallback(
    async (
      endpoint: string,
      body?: any,
      config?: AxiosRequestConfig,
      method: "get" | "post" | "delete" | "patch" = "get"
    ) => {
      setLoading(true);
      await axios[method]<T>(endpoint, body, config)
        .then((res) => {
          setData(res.data);
          setLoading(false);
        })
        .catch((err) => {
          setError(err);
          setLoading(false);
        });
    },
    []
  );

  return { data, loading, error, loadData };
};

type ResponseType = {
  userId: number;
  id: number;
  title: string;
  body: string;
};

export const MyComponent = (): JSX.Element => {
  const { data, error, loadData, loading } = useAxios<ResponseType>();

  React.useEffect(() => {
    loadData("https://jsonplaceholder.typicode.com/posts/1");
  }, []);

  return (
    <div>
      {loading && "Loading..."}
      {data && (
        <>
          {data.title}
          {data.userId}
        </>
      )}
      {error && JSON.stringify(error)}
    </div>
  );
};

Thanks for your time, see you next time!!

Did you find this article valuable?

Support Arpit Bhalla by becoming a sponsor. Any amount is appreciated!