Using Axios for Network Requests in React

Before jumping ship to React, I had been working on Angular for a long time and really enjoyed building great SPAs in the MVVM Pattern. One of my favorite things was the services architecture of making requests. I’ve tried to recreate the pattern using Axios, which you can use in React or any other frontend framework.

First, let’s define a custom wrapper around Axios for our application. This can contain our global configuration such as the base API url, header defaults and more:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import axios     from 'axios'
import constants from 'shared/constants'



/**
 * Create an Axios Client with defaults
 */
const client = axios.create({
  baseURL: constants.api.url
});



/**
 * Request Wrapper with default success/error actions
 */
const request = function(options) {
  const onSuccess = function(response) {
    console.debug('Request Successful!', response);
    return response.data;
  }

  const onError = function(error) {
    console.error('Request Failed:', error.config);

    if (error.response) {
      // Request was made but server responded with something
      // other than 2xx
      console.error('Status:',  error.response.status);
      console.error('Data:',    error.response.data);
      console.error('Headers:', error.response.headers);

    } else {
      // Something else happened while setting up the request
      // triggered the error
      console.error('Error Message:', error.message);
    }

    return Promise.reject(error.response || error.message);
  }

  return client(options)
            .then(onSuccess)
            .catch(onError);
}

export default request;

Making Requests using Services

To make a simple request, we can use something like this:

1
2
3
4
5
6
7
8
import request from 'shared/lib/request'

request({
  method: 'get',
  url: '/path/'
}).then((resp) => {
  console.log(resp);
})

But the ideal way to use it is to create a separate service for each resource that should be responsible for handling all API calls of that model. For example, for a Message class, we can create a MessageService:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// services/api/message.js

import request from 'shared/lib/request'

function get(id) {
  return request({
    url:    `/message/${id}`,
    method: 'GET'
  });
}

function create({subject, content}) {
  return request({
    url:    '/message/create',
    method: 'POST',
    data:   {
      subject,
      content
    }
  });
}

const MessageService = {
  get, create //, update, delete, etc. ...
}

export default MessageService;

You can then call these methods from any other module/view/component:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react'
import MessageService from 'services/api/message'

class Message extends React.Component {
  handleSubmit() {
    const {subject, message} = this.state;

    MessageService
      .create({subject, message})
      .then((response) => {
        alert(`New Message with id ${response.id} created!`);
      });
  }

  // Other stuff...
}