December 21, 2023

HTTP GET Method in React - fetch, Axios

In web application we need to use HTTP requests to call APIs to do CRUD operations. Most used HTTP methods for these operations are- GET, PUT, POST, PATCH, DELETE. In this post we'll see how to use HTTP GET method from React applications in order to get resources from a server.

React Example HTTP GET method

In this example we'll see usage of both fetch() method in Fetch API and Axios.

  • fetch()- This method is used to call APIs across the network. GET is the default for fetch method. Though the name is fetch() but don't get confused it can be used for POST, DELETE, PUT, PATCH operations too.
    With fetch() method you pass the path to the resource you want to fetch and it returns a promise that resolves with a Response object.
  • Axios- It is a promise-based HTTP Client for node.js and the browser.

For API calls JSONPlaceholder is used which is a free fake API for testing and prototyping.

Using HTTP GET method in React with fetch

fetch() method takes one mandatory argument; path to the resource (API), it also accepts a second parameter, an init object that allows you to control a number of different settings. Here is the fetch method format for a POST request where you need to explicitly specify the method you are using and the object that you want to send.

fetch(url, {
    method: "POST", // *GET, POST, PUT, DELETE, etc.
    mode: "cors", // no-cors, *cors, same-origin
    cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
    credentials: "same-origin", // include, *same-origin, omit
    headers: {
      "Content-Type": "application/json",
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: JSON.stringify(data), // body data type must match "Content-Type" header
  });

Since GET method is default for fetch and no object has to be sent so second parameter is not needed, we just need to pass the URL to connect to API for fetching resource.

In the example there are two Components- Posts and PostItem.

Posts component does the job of fetching posts (limited to 10 posts). For that fetch() method is used which returns a Promise, using promise chaining first the response object is converted to JSON data and then set to the Posts state. There is also a catch part to handle the scenario when the Promise is rejected.

Posts.js

import { useEffect, useState } from "react";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  useEffect(()=>{
    fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
    .then((response) => response.json())
    .then((resData) => setPosts(resData))
    .catch((error) => console.log(error.message))
  }, [])

  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
          <PostItem key={post.id} post={post}></PostItem>
      )}
    </div>
  )
}

export default Posts;

In the code-

  1. useState() hook is used to maintain Posts state variable.
  2. fetch() method is called with in the useEffect() hook, that way you avoid an infinite loop. If you don’t wrap the fetch() in useEffect the setting of state variable- setPosts(resData) will result in state change and re-rendering and the same thing repeated again and again. With the useEffect() hook call will happen only once because the dependency array (second argument in useEffect()) is empty.
  3. Once posts are fetched post data is sent to PostItem component to display the post data.
  4. Note that Bootstrap 5 is used for styling here. Refer Installing Bootstrap in React to know how to install Bootstrap in your React application.

PostItem.js

const PostItem = (props) => {
  return (
    <>
      <h3>{props.post.title}</h3> 
      <span>{props.post.body}</span>
    </>
  );
}

export default PostItem;

Using async/await with fetch

Using async/await is easier than using Promise directly so that is the preferred way. You can use try/catch to handle errors with async/await.

import { useEffect, useState } from "react";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  useEffect(()=>{
    const postData = async () => {
      try{
        const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10');
        // check for any error
        if(!response.ok){
          throw new Error('Error while fetching post data');
        }
        const responseData = await response.json();
        setPosts(responseData);
      }catch(error){
        console.log(error.message);
      }
    }
    postData();
  }, []);

  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
        <PostItem key={post.id} post={post}></PostItem>
      )}
    </div>
  )
}
export default Posts;

In the code, note the following-

  1. Async is not directly used in useEffect function. You write a separate function with in useEffect() and make that async. That way you don’t affect the cleanup function which may otherwise never get called.
  2. Check for the response status and throw an error if response status is not ok.
  3. You need to explicitly call the async function you have written within useEffect() as done by calling postData();

Showing error message With React HTTP GET example

In the above React fetch method example with async/await error message is logged to the console. If you want to display the error to the user then you can create one more component for Error.

ErrorMessage.js

Uses the Bootstrap alert to show the error message.

const ErrorMessage = (props) => {
  return(
    <>
      <div className="alert alert-warning alert-dismissible fade show" role="alert">
        <p>{props.message}</p>
              
        <button type="button" className="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
      </div>
    </>
  )
}
export default ErrorMessage;

Posts.js

Updated to have Error state variable and the logic to show error.

import { useEffect, useState } from "react";
import ErrorMessage from "./ErrorMessage";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState();
  useEffect(()=>{
    const postData = async () => {
      try{
        const response = await fetch('https://jsonplaceholder.typicode.com/postsss?_limit=10');
        // check for any error
        if(!response.ok){
            throw new Error('Error while fetching post data');
        }
        const responseData = await response.json();
        setPosts(responseData);
      }catch(error){
        setError(error);
      }
    }
    postData();
  }, []);

  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
          <PostItem key={post.id} post={post}></PostItem>
      )}
    </div>
  )
}

export default Posts;

Using HTTP GET method in React with Axios

If you want to use Axios library to make HTTP calls then the first thing is to install the Axios library.

Using npm

$ npm install axios

Using yarn

$ yarn add axios

Axios returning Promise - React Example

import axios from "axios";
import { useEffect, useState } from "react";
import ErrorMessage from "./ErrorMessage";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState();
  useEffect(()=>{
    axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10')
    .then((response) => setPosts(response.data))
    .catch((error) => setError(error))
  }, []);

  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
          <PostItem key={post.id} post={post}></PostItem>
      )}
    </div>
  )
}
export default Posts;

Some points to note here-

  1. Axios returns a Promise that resolves to a response object which has a data property containing the fetched data.
  2. (response) => setPosts(response.data)
    
  3. With Axios default behavior is to reject every response that returns with a status code that falls out of the range of 2xx and treat it as an error.
  4. Error message gives a quick summary of the error message and the status it failed with.
  5. There is no change in other 2 components PostItem and ErrorMessage. Please refer the above example to get the code for these components.

Using async/await with Axios - React Example

import axios from "axios";
import { useEffect, useState } from "react";
import ErrorMessage from "./ErrorMessage";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState();
  useEffect(()=>{
    const postData = async () => {
      try{
        const response = await axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10');
        setPosts(response.data);
      }catch(error){
        setError(error);
      }
    }
    postData();
  }, []);

  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
          <PostItem key={post.id} post={post}></PostItem>
      )}
    </div>
  )
}

export default Posts;

That's all for the topic HTTP GET Method in React - fetch, Axios. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment