How to use Axios with React (Everything you need to know)

Learn everything you need to know about using Axios with React. This article covers integrating Axios with React, the proper lifecycle hook to make requests, the most common request types and how properly handle errors.

How to use Axios with React (Everything you need to know)

Axios is among the most popular promise based HTTP clients for both browsers and Node.js. At the time of writing this article, it’s floating at around 4 million weekly downloads on NPM only.

It’s simple, lightweight and easy to customize. Not only that, but works great with React and many other frameworks.

Axios provides support for request and response interceptors, transformers and auto-conversion to JSON. It’s also protecting you by default against cross-site request forgery (XSRF).

βš›οΈ Here's everything you need to know about using Axios with React! #axios #react Click To Tweet

In this short tutorial, we’ll cover:

Before we start, let’s create a new project using create-react-app. The process is very straightforward.

# Create a new app.
create-react-app axios-react-tutorial

# Move inside our new project.
cd axios-react-tutorial

# Install dependencies.
yarn add axios shards-react

# Start the project.
yarn start

Once you start the project, you should see the default React welcome page:

Create react app demo preview.

We’ll need only Axios and Shards React as our dependencies. We’ll use the Shards React UI kit to make our UI data look sleek. 😎

Next, open the project in your favourite editor, and let’s dive right in! πŸŠβ€β™‚οΈ

Integrating and configuring Axios in your React project

By default, our project is pretty empty. We’ll fix this by creating a new directory called utils. Inside, let’s also create a new file called API.js in which we’ll store our Axios configuration.

// utils/API.js

import axios from "axios";

export default axios.create({
  baseURL: "https://randomuser.me/api/",
  responseType: "json"
});

The code inside API.js imports Axios and exports a new configured instance of it. It’s set up to use the RandomUser API as a base URL and also specify that we’d like JSON in return.

Finally, you can create a new file User.js and inside paste the following component. The User component will serve as our user placeholder card.

import React from "react";
import PropTypes from "prop-types";

import "bootstrap/dist/css/bootstrap.min.css";
import "shards-ui/dist/css/shards.min.css";

import { Card } from "shards-react";

class User extends React.Component {
  render() {
    const { name, avatar, email, isLoading } = this.props;

    const userDetails = (
      <div>
        <img
          className="img-thumbnail rounded-circle mx-auto mb-2 shadow-sm"
          src={avatar}
          alt={name}
          style={{ width: "100px", height: "100px" }}
        />
        <h4 className="mb-0">{name}</h4>
        <span className="text-muted">{email}</span>
      </div>
    );

    const loadingMessage = <span className="d-flex m-auto">Loading...</span>;

    return (
      <Card
        className="mx-auto mt-4 text-center p-5"
        style={{ maxWidth: "300px", minHeight: "250px" }}
      >
        {isLoading ? loadingMessage : userDetails}
      </Card>
    );
  }
}

User.propTypes = {
  name: PropTypes.string,
  avatar: PropTypes.string,
  email: PropTypes.string,
  isLoading: PropTypes.bool
};

export default User;

The User component is a simple component that displays a user avatar, his or her name and email inside a card. It accepts an isLoading boolean prop, which if is set to true it will display a Loading... message. Otherwise, it will display the actual user details.

Next, open src/App.js and delete everything inside. We won’t need it anyway.

Let’s use this opportunity to see how our User card looks like with some plain data.

// src/App.js

import React from "react";

class App extends React.Component {
  render() {
    return <User name="Jessica Doe" avatar="..." email="hello@jessica.com" />;
  }
}

export default App;

Make sure to provide an image URL to your avatar prop.

React app simple app preview

This looks good so far, but let’s load some “real” fake data using an asynchronous request and see how that goes.

In which lifecycle hook should we make our request?

Ok, we have a component, but where should we make the actual request to our API to load the data? The answer is inside the componentDidMount() lifecycle hook.

Based on the official React documentation, this is the perfect place for such an action.

React docs component did mount

If you need to load data from a remote endpoint, componentDidMount() is a good place to make requests.

Perfect! Now that we know where we should load our data, let’s make our first GET request. But first, let’s update our App.js component so we can integrate the request logic.

// src/App.js

import React from "react";

import API from "./utils/API";
import User from "./User";

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isLoading: true,
      name: null,
      avatar: null,
      email: null
    };
  }

  render() {
    const { isLoading, name, avatar, email } = this.state;

    return (
      <User isLoading={isLoading} name={name} avatar={avatar} email={email} />
    );
  }

  async componentDidMount() {
    // Load async data.
    // Update state with new data.
    // Re-render our component.
  }
}

export default App;

GET Requests

Now the App.js component has its own state. That will help with keeping track of the loading state, the person’s name, avatar and email. It’s also using the state data to hydrate the User component when the component is re-rendered.

We also created the async componentDidMount() method. Inside, we make an asynchronous request to load the data and update our component’s state. That will trigger a new re-render.

Notice that the method is async which will allow us to await certain actions inside.

Finally, let’s update the method to GET tge data from the remote server.

    // src/App.js

    // ...

      async componentDidMount() {
        // Load async data.
        let userData = await API.get('/', {
          params: {
            results: 1,
            inc: 'name,email,picture'
          }
        });

            // Parse the results for ease of use.
        userData = userData.data.results[0];

        // Update state with new data and re-render our component.
        const name = `${userData.name.first} ${userData.name.last}`;
        const avatar = userData.picture.large;
        const email = userData.email;

        this.setState({
          ...this.state, ...{
            isLoading: false,
            name,
            avatar,
            email
          }
        });
      }

    // ...

    export default App;

That’s a lot of code, let’s break it down step by step:

// ...

let userData = await API.get("/", {
  params: {
    results: 1,
    inc: "name,email,picture"
  }
});

// ...

Inside the async componentDidMount() method, we are making an asynchronous GET request. We’re making this request off the base URL only (notice the forward slash /). We’re also sending two params, specifying how many results and which details we expect. In this case it’s the name, email and avatar.

// ...

userData = userData.data.results[0];

// ...

When the action completes, we store the data inside the userData variable. Next, we update the variable with the returned data for ease of use.

Finally, we create easy to use variables (name, avatar, email) and update the state with their values.

Handling Errors with Async/Await

The usual way of handling errors in JavaScript when using promises, is via the .catch() method. The beauty of using async/await is thet we can forget about that and use try/catch statements instead.

Here’s how the request above would be rewritten using try/catch. The request is also adjusted so it will fail.

// ...

try {
  // Load async data from an inexistent endpoint.
  let userData = await API.get("/inexistent-endpoint");
} catch (e) {
  console.log(`😱 Axios request failed: ${e}`);
}

// ...

And of course we get the error logged in our console.

The catch block is the perfect place to parse the returned error. It’s also a great place to show your users an appropriate feedback message.

Axios try catch error demo

Using Mockable to mock our other requests

We now know how almost everything works in Axios. We can now break away from our example and explore other Axios methods in more depth. In the next part of the tutorial, we’ll do so without focusing on presentation.

For this to work, we can use Mockable, a free REST API mocking tool that we can configure as we wish.

Mockable interface demo

Using Mockable I was able to mock the other three request types we will explore in this article: POST, PATCH and DELETE. You can download my mock REST api here so you can use it as a starting point.

Get Mockable API Export

Using the mock API, I am able to make the following requests using Axios:

POST Requests

In Axios, you can create POST requests using the .post() method and passing the data as a second parameter. Here’s the method’s signature for your reference.

axios.post(url[, data[, config]])

Using the mocked endpoint above, our POST request would become:

import axios from "axios";

try {
  const response = await axios.post('http://demo0725191.mockable.io/post_data', { posted_data: 'example' });
  console.log('πŸ‘‰ Returned data:', response);
} catch (e) {
  console.log(`😱 Axios request failed: ${e}`);
}

And the returned response shows that the data has been successfully POSTed.

Axios POST request.

PATCH Requests

PATCH requests are also extremely similar and can be created using the .patch() method. Here’s the signature for your reference:

axios.patch(url[, data[, config]])

Using the mocked endpoint above, our PATCH request becomes:

import axios from "axios";

try {
  const response = await axios.patch('http://demo0725191.mockable.io/patch_data', { new_name: 'My new cool name!' });
  console.log('πŸ‘‰ Returned data:', response);
} catch (e) {
  console.log(`😱 Axios request failed: ${e}`);
}

And the data is successfully updated when our request finished.

Axios PATCH request

DELETE Requests

I guess that it goes without saying that DELETE requests are also easy and can be created using the .delete() method. Here’s the signature for your reference.

axios.delete(url[, config])

Using the mocked endpoint above, our DELETE request becomes:

import axios from "axios";

try {
  const response = await axios.delete('http://demo0725191.mockable.io/delete_data');
  console.log('πŸ‘‰ Returned data:', response);
} catch (e) {
  console.log(`😱 Axios request failed: ${e}`);
}

And the data is successfully deleted from our mocked server:

Axios DELETE request

Conclusion

Handling requests in React with Axios is very easy to understand. There’s room for improvement, like adding more abstractions and structure, but that’s for another time.

What do you think about using React and Axios? Are there any certain features do you think I missed or should be covered? Let me know in the comments below!

Also, if you liked the article, make sure to share it with your friends!

βš›οΈ Here's everything you need to know about using Axios with React! #axios #react Click To Tweet

Catalin Vasile

Catalin Vasile

Catalin is a design focused engineer and founder of DesignRevision. When he’s not working on a project, he likes to read, watch movies and take long hikes.

πŸ€” What do you think?

Introducing

Shards Dashboard Pro

A premium & high-quality Bootstrap 4 admin dashboard template pack.

Here's a 10% discount code! DR10OFF Check it Out