How to make API request in React.js?

In this tutorial, you’ll learn how to create some API request in React.js, receive data from an API and finally display the data on the DOM.

Make sure you’ve read the tutorial on Handling User Input and Forms, because you’re going to continue the same project from here.

You’re going to use an API called Unsplash API to get the images for the requests made to the Unsplash server.

To get started, go to unsplash.com/developers

Next, click “Register” or “Register as a developer” and sign up. Once signed up, click on Your apps and then “New App” (https://unsplash.com/oauth/applications)

Give some name and description to your app.

Once done, click on your app name, scroll down to Keys, and copy the Access Key. Keep this key somewhere safe – You’ll need it later

Using Axios to make API request

The NPM package that you’re going to use to make API requests to the Unsplash server is called axios.

First of all, go to the project directory and from terminal / CMD, run the following command:

npm install axios --save

Once it finishes installing it, go to App.js file and import axios as follows:

import axios from ‘axios’;

Next up, modify the onSearchSubmit() function in App.js as follows:

Method 1:

import React from 'react';
import axios from 'axios';
import SearchBar from './SearchBar';

class App extends React.Component {

    onSearchSubmit(term){
        axios.get("https://api.unsplash.com/search/photos", {
            params: { query: term },
            headers: {
                Authorization:
                "Client-ID a1352d9b662afe6c8ce64dfb3929c20c21aef2aa281d7377da9cc522e0284d0f"
            }
        }).then(response => {
            console.log(response.data.results);
        });
    }

    render(){
        return(
            <div className="ui container" style={{ marginTop: '10px'}}>
                <SearchBar onSubmit={this.onSearchSubmit} />
            </div>
        );
    }
}

export default App;

In the above code, onSearchSubmit() function takes in the term as passed from SearchBar component. Next, you make a GET request using axios.get().

axios.get() takes in two parameters. The first parameter is the URL where the API request is made. The second parameter contains some configurational information about the request. params contain the query string, the keyword that is being passed for searching the term.

Inside headers object, there’s a property called “Authorization” with a Client-ID. This property is needed by the unsplash API to determine who is making the request. After the Client-ID, you need to paste the access key which you previously copied and kept for later use.

Keep in mind, the request you’re making is asynchronous in nature. Which means, the request is going to take some amount of time to complete. Once it is completed, you can figure out what to do next with the then() promise. then() is a promise and a callback function in JavaScript which is executed only if the request succeeds.

The then callback can contain the data that is received from the GET request. You can call it whatever you want. In this case, I’ve called it response due to community convention. Now, there’s another object inside response called data (it is named by Unsplash API) which contains the arrays of data called results. If you console log response.data.results and re-run the server by proving some image search term like “trees” or “mountains” or “people” or “cars”, you should see the results in the console window.

Method 2:

You can do the same thing with async – await (very popular among JavaScript developers these days). All you have to do is put async in front of the function name inside which the network request is being made. Here, the function name is onSearchSubmit and the network request (GET request) is being made through axios.get(). So, you put async in front of onSearchSubmit and put await in front of axios.get().

Once that’s done, you don’t need to use then() promise anymore. You can access the received data after the network request, anywhere inside the class. All you have to do is, assign the received result in a variable. Here, I’m calling this variable response. So, the modified code would look like:

import React from 'react';
import axios from 'axios';
import SearchBar from './SearchBar';

class App extends React.Component {

async onSearchSubmit(term){
    const response = await axios.get("https://api.unsplash.com/search/photos", {
        params: { query: term },
        headers: {
        Authorization:
        "Client-ID a1352d9b662afe6c8ce64dfb3929c20c21aef2aa281d7377da9cc522e0284d0f"
        }
      });
    console.log(response.data.results);
}

render(){
    return(
        <div className="ui container" style={{ marginTop: '10px'}}>
        <SearchBar onSubmit={this.onSearchSubmit} />
        </div>
    );
 }
}

export default App;

Setting up setState after async request

Now that you’ve set up some code to receive data, there should be some way to re-render the component and display some of the data. You can easily render the component by using setState() method. But before that, you must declare some variables to store the states. So, right inside App class, declare states as follows:

state: { images: [] }

And instead of consoling out console.log(response.data.results), replace the statement with:

this.setState({ images: response.data.results });

Now, the resultant array is saved in images property of the state.

Let’s try to show the number of found images after the SearchBar component. You can do that as follows:

{this.state.images.length} images found!

App.js should now look like:

import React from 'react';
import axios from 'axios';
import SearchBar from './SearchBar';

class App extends React.Component {

state = { images: [] };

async onSearchSubmit(term){

const response = await axios.get("https://api.unsplash.com/search/photos", {
params: { query: term },
headers: {
Authorization:
"Client-ID a1352d9b662afe6c8ce64dfb3929c20c21aef2aa281d7377da9cc522e0284d0f"
}
});

this.setState({ images: response.data.results });

}

render(){
return(
<div className="ui container" style={{ marginTop: '10px'}}>
<SearchBar onSubmit={this.onSearchSubmit} />
    {this.state.images.length} images found!
</div>
);
}
}

export default App;

Now, if you save the file and run the server and make a image search, you’ll get an error that says something like:

Unhandled Rejection (TypeError): this.setState is not a function

This is because onSearchSubmit() is not an arrow function although we’re using this.setState inside the function. React doesn’t know that this belongs to the App component. So, let’s convert the onSearchSubmit() function into an arrow function and adjust async – await placements as required:

onSearchSubmit = async (term) => {

const response = await axios.get("https://api.unsplash.com/search/photos", {
params: { query: term },
headers: {
Authorization:
"Client-ID a1352d9b662afe6c8ce64dfb3929c20c21aef2aa281d7377da9cc522e0284d0f"
}
});

this.setState({ images: response.data.results });

};

Use custom API configuration in React.js

Right now, everything works fine but there’s too much configuration stuff right inside the App component. You must think that there should be a way to clean this up a bit. And of course, you’re right about that.

Inside the src folder, create a new directory called api. Inside that, create a new file called unsplash.js. You’re going to move some of the network configuration stuff to the API file. Inside unsplash.js, write the following code:

import axios from 'axios';


export default axios.create({
baseURL: "https://api.unsplash.com",
headers: {
Authorization:
"Client-ID a1352d9b662afe6c8ce64dfb3929c20c21aef2aa281d7377da9cc522e0284d0f"
}
});

Next, in App.js, remove the headers object from axios.get() method and change the GET request URL to /search/photos.

After that, remove axios import statement from App.js file and import unsplash API instead.

App.js should now look like:

import React from 'react';
import unsplash from '../api/unsplash';
import SearchBar from './SearchBar';

class App extends React.Component {

state = { images: [] };

onSearchSubmit = async (term) => {
const response = await unsplash.get("/search/photos", {
params: { query: term }
});

this.setState({ images: response.data.results });

};

render(){
return(
<div className="ui container" style={{ marginTop: '10px'}}>
<SearchBar onSubmit={this.onSearchSubmit} />
{this.state.images.length} images found!
</div>
);
}
}

export default App;

 

Leave a Comment