DEV Community

loading...
Cover image for How to manage API calls in React ⚛️

How to manage API calls in React ⚛️

Adyasha Mohanty
Creative Frontend Developer. Works with React, Redux and in love with Next.js ♡
Originally published at adyablogs.tech Updated on ・5 min read

React library is well known for building rich and highly scalable user interfaces. There are many ways to fetch data from an external API in React.

Before you go through this blog be familiar with React library and Application Programming Interface (API).

In this blog, we will discuss different ways to manage API calls in React. In the end, you will be able to choose the best approach based on the application requirements.

1. The Fetch API

Fetch API is built into most modern browsers on the window object (window.fetch) and enables us to make HTTP requests very easily.

The following code snippets show a simple example of using Fetch API in practice.

import {useEffect} from "react";

const fetchUsers = () => {
// Where we're fetching data from
return fetch("http://www.abc.cd/test")
// We get the API response and receive data in JSON format
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch ((error) => console.error(error));}
Enter fullscreen mode Exit fullscreen mode

The only goal of this function is to access the data and to convert the response into JSON using the response.json() method.
Here, the use of the json() method is to get the response object which is stored in data and used to update the state of users in our application.

The fact that Fetch is promise-based means we can also catch errors using the .catch() method. Any error encountered is used as a value to update our error’s state.

Added to that, we make this request within the useEffect() hook with an empty dependencies array as the second argument so that our request is only made once, not dependent on any other data.
Here is an example how to use it in useEffect() hook:

import {useEffect} from "react";

useEffect(() => {
    fetchData()
  }, []);
Enter fullscreen mode Exit fullscreen mode

Isn’t this handy! Let’s see what other methods do 😃.


2. Axios Library

Axios is a Promise-based HTTP client for JavaScript which can be used in your front-end application and your Node.js backend.
By using Axios it’s easy to send asynchronous HTTP requests to REST endpoints and perform CRUD operations.

In this example, we have to first install Axios using npm or yarn and then add it as an import to your parent component.

npm install axios
Enter fullscreen mode Exit fullscreen mode

The following code snippets show an example of using Axios:

import axios from "axios"

const fetchData = () => {
return axios.get("http://www.abc.cd/test")
   .then((response) => console.log(response.data));
}
Enter fullscreen mode Exit fullscreen mode

Similar to the Fetch API, Axios also returns a promise. But in Axios, it always returns a JSON response. The coding part is similar to the Fetch API, except for shorter steps and better error handling.

Check out the official documentation for better knowledge.


3. Async-Await syntax

Async/await is a relatively new way to write asynchronous code synchronously.

The async keyword before a function has two effects:

  • Make it always return a promise.
  • Allows await to be used in it.

The await keyword before a promise makes JavaScript wait until that promise settles, and then:

  • If it’s an error, the exception is generated.
  • Otherwise, it returns the result.

The following is the code snippets :

async function fetchData() {
    try {
      const result = await axios.get("http://www.abc.cd/test")
      console.log(result.data));
    } catch (error) {
      console.error(error);
    }
  }
Enter fullscreen mode Exit fullscreen mode

When we use useEffect(), the effect function (the first argument) cannot be made an async function. For that, we can create a separate async function in our component, which we can call synchronously within useEffect and fetch our data accordingly.


4. Custom React Hook

A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks. The idea behind custom hooks is to extract component logic into reusable functions.

So let's call our custom hook: useFetch. This hook accepts two arguments, the URL we need to query to fetch the data and an object representing the options we want to apply to the request.

Alright! Now, let's see how easy it is to fetch data with our useEffect() hook. We are going to use the Fetch API to make our request. For that, we have to pass the URL and the options we want to retrieve. From there, we get an object that we can use to render our application.

import { useState, useEffect } from 'react';
const useFetch = (url = 'http://www.abc.cd/test', options = null) => {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch(url, options)
      .then(res => res.json())
      .then(data => setData(data));
  }, [url, options]);
  return {data}
}
export default useFetch;
Enter fullscreen mode Exit fullscreen mode

We can call whenever we need to fetch data inside our application.

import useFetch from './useFetch';
  const { data } = useFetch( 'http://www.abc.cd/test' );
  console.log(data);
Enter fullscreen mode Exit fullscreen mode

5. React Query Library

React-query is a great library that solves the problem of managing server state and caching in applications.

"It makes fetching, caching, synchronizing, and updating server state in your React applications a breeze”

Firstly, let’s install the required package

npm install react-query react-query-devtools
Enter fullscreen mode Exit fullscreen mode

Note: React Query also has its own dev tools which help us to visualize the inner workings of React Query.

React-query gives us a cache, which you can see below through the React Query Devtools. This enables us to easily manage the requests that we have made according to the key value that we specify for each request.

import React from "react";
import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider, useQuery } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";

const queryClient = new QueryClient();

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <FetchData />
    </QueryClientProvider>
  );
}

function FetchData() {
  const { data } = useQuery("UserData", () =>
    fetch("http://www.abc.cd/test").then((res) => res.json())
  );

  return (
    <div>
       // data you want to show
      <ReactQueryDevtools initialIsOpen />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Enter fullscreen mode Exit fullscreen mode

In short, we just need to tell the library where you need to fetch the data, and it will handle caching, background updates, and refresh data without any extra code or configuration.

It also provides some hooks or events for mutation and queries to handle errors and other states of side effects which remove the need for useState() and useEffect() hooks and replaces them with a few lines of React Query logic.

For better insights check out the official documentation.

There are various other ways to manage data fetching such as SWR, GraphQL API, but this blog post is not actually explaining them in depth but you can check it out :)


That's all about it. By the way don't forget to check out the comment section of the following tweet. This might help you to choose the best approach.

Happy coding 😉. Thank you for reading my blog 💖.

Feel free to connect on Twitter :)




Discussion (11)

Collapse
mpagels profile image
Martin Pagels • Edited

Hey Adyasha Mohanty,

I think I found a huge mistake in your "custom hook" part. You are missing a "return" statement here. Right now it is broken and would break the hole app if useFetch would be imported.

I would add here:
dev-to-uploads.s3.amazonaws.com/up...

Please check your code for errors before publishing it to an audience. You would do that before putting the code into production, wouldn't you?

Collapse
dylanwatsonsoftware profile image
Dylan Watson • Edited

Come on, 1 mistake doesn't negate a great article. Especially since the article is to inform, not for you to simply copy and paste.

Great stuff @adyasha8105 !

Collapse
mpagels profile image
Martin Pagels

Thx for your feedback. I’m sorry if you thought that one mistake „negated“ the whole article for me.
This was not my goal. I just think it's important to use correct code on this kind of website, especially for users who are learning from this kind of articles. They shouldn't get confused or even discouraged when trying to understand or copy the code snippet and it doesn’t work.

Collapse
adyasha8105 profile image
Adyasha Mohanty Author • Edited

Thank you @dylanwatsonsoftware !
It's so nice of you and I agree I did a mistake. It's not the mistake that matters but what actually matters is how you deal with it, what you learn from it and how you apply that lesson. And I am happy @mpagels pointed out that mistake.

Collapse
adyasha8105 profile image
Adyasha Mohanty Author • Edited

Hey @mpagels ,
Thank you for pointing out a big mistake I did. Sorry for the inconvenience cause to you. I had checked my code but I don’t know how that one line got missed.
Once again thank you Martin. I am glad people are actually reading my code and pointing out mistake.

Collapse
mpagels profile image
Martin Pagels

Hey,
good we catched the error together. :-)
Great article by the way.

Collapse
sylflo profile image
Sylvain Chateau • Edited

If we are talking about react-query, it would have been nice to at least mentioned SWR

Collapse
adyasha8105 profile image
Adyasha Mohanty Author

Thanks @sylflo for mentioning these things :) I have added another line at the end about other ways for data fetching like SWR and GraphQL.

Collapse
sylflo profile image
Sylvain Chateau

My points was that those two libraries do actually pretty much the same thing, and are direct concurrent. But anyways I guess most people already know SWR

Collapse
mogaozq profile image
Mohammad Barbast

Just react-query, nice and clean

Collapse
nemethricsi profile image
Richard

npm react-use-promise is also good :)