How to Fetch Data From an API in React.js

Written by Shakhawat-Hossain | Published 2020/12/16
Tech Story Tags: reactjs | api | asynchronous | javascript | framework | components | web-development | hackernoon-top-story

TLDRvia the TL;DR App

Without any doubt, the use of React is increasing day by day. And also API(Application Programming Interface) is gaining more popularity in the modern era of technology. This article will guide a beginner to play with React to API.
Assume that we want to fetch a list of pictures when a page gets loaded. So, First of all, we need an API that provides such information. The most used and easy to access API I have found is Unsplash. Now the main question, how our application is going to work. Without any delay, let's hop onto it.
Our app is going to run on a web browser. As our page gets loaded, it will create an ajax request or a network request over to an API called Unsplash API. Unsplash is a company that provides free images for developers. Now the API takes that request and returns a big list of JSON data based on the keyword that is attached to it. Then we can take the required info from that JSON data to use it in our app. As we know the basic flow of our project, let's complete some initial setup to start the project.
First of all, we need a dedicated project to contain all of our code. So let's create a react project by using command create-react-app. I am going to call my project ‘learn-api’. So on the terminal, we have to execute create-react-app learn-api. This will take some time to set up a default react app for us.
I love to use the Visual Studio Code as a code editor. You can use anyone. As we create our project, we will see some default files and folders.
We are gonna start from scratch. So let's delete the files inside the src folder. Create a file called index.js inside src and add the following lines inside it.
import React from 'react';
import ReactDOM from 'react-dom';

import App from './components/App';

ReactDOM.render(
<App />, document.querySelector('#root')
);
Create a folder called components and inside that create file App.js. Also, fill them with the following line of codes.
import React from 'react';

const App = () => <div>App</div>;

export default App;
On the terminal, run yarn start to execute the script file. If you see 'App' rendering on your browser, bravo, we have configured our app properly. Now let's have a look at our mock-up design.
Our main purpose is to fetch data from API so I will make the UI simple. Will use bootstrap to style the page. To use bootstrap on terminal run yarn add bootstrap also at the top of index.js file add import 'bootstrap/dist/css/bootstrap.min.css'; line. That’s it, Bootstrap has been added in our app.
In our mock-up, we can see mainly one component, ImageList. If we want, we can create another sub-component called Image. Let's start with the core one. So our App component is going to contain the ImageList component. Let's generate it. Create a file called ImageList.js inside the components folder and fill it with the following code.
import React from 'react';

const ImageList = () => {
    return <div>ImageList</div>
};

export default ImageList;
We have to integrate ImageList with our App. To make that happen, we have to update our App.js.
import React from 'react';

import ImageList from './ImageList';

const App = () => {
    return(
        <div>
            <ImageList />    
        </div>
    );
};

export default App;
On our browser, we should see ImageList. So far it seems simple. Now we have to dive a little bit deeper. At this point, we will talk a little about React State and Lifecycle.

State:

The state is the heart of every react component. Which controls the behavior of a component. In one word, the State of a component is an object that contains some information that may get changed based on the lifetime of that component.
To use state we have to convert our functional component into a class-based component(Technically, we can use State in functional component by using hooks system. But we are not going to use that). Now the main question, Why do we need state in our app. Well, because the task we need to cover matches the specification of State. As our page gets loaded, we want to store the list of images. After that, we want to render them on the page. In summary, our page indicates a lifetime(When it gets loaded) and an instance(After getting loaded we need to access the data.), which matches the definition of State.

Component LifeCycle:

A component lifecycle method is a function that we can optionally define inside our class-based component. If we implement them in our component, it will get executed at some point. There are mainly three methods. In our scenario, we only need the componentDidMount method. Cause we want our page to get rendered and then the network request to happen. After that, we want to place images on our page. To complete that, the componentDidMount method is a perfect fit.
So first thing first, let's convert our App component from functional component to class-based component. We need a constructor to assign our state initially. As initially, we don't have any list of images. So we will initialize our state with an empty list. We also need a method called componentDidMount(which will handle the task to fetch data from the API). For now, it will provide output on the browser console. If we see "I will get called once the page gets loaded" on the browser, for sure, we have achieved our first milestone.
To get a similar output, we have to add the following codes inside App.js.
import React from 'react';

import ImageList from './ImageList';

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {imageList: []}
    }

    componentDidMount() {
        console.log("I will get called once the page gets loaded");
    }

    render() {
        return(
            <div>
                <ImageList />    
            </div>
        );
    }
}

export default App;
We haven't talked about the API yet. Let's have a look at it. We need to look at the official page of the API. The first thing we need to do is register as a developer. Once you are logged in you have to create a project. If you click on your apps, you will find an option to create one. They will ask you to accept some rules, and we are going to accept them.
Once you click on accept terms, it's going to ask you for your app name and a description. As you fill the fields you will be redirected to another page. If you scroll down a little bit further you will see the keys section. There we will find the Access key. As we have the access key, now all we need to know is the use of that key. So let's click on the documentation.
As our target is to fetch photos based on a search that matches the text that we will provide. There it will show you how to use it. To use it on our page, we are going to use a third-party package. Cause it is not going to be the job of React library itself to request the Unsplash API. For us Axios gonna take care of that. To add it we need to close the running project. On terminal run 'yarn add Axios', it will install Axios on our project. We want to fetch data at our App component. So first thing first, we have to import Axios. Now by the convention, we put imports of the third party above the files we have created.
As we import that we have to request the API. If we check the documentation it says we have to make a get request to the endpoint 'search/photos'. In Axios, we do 'get' requests by axios.get(). Which takes two arguments, the address of the API and a set of options. The location of the API is 'https://api.unsplash.com/'. The final endpoint for us is 'https://api.unsplash.com/search/photos'. If we want to get data, we have to authenticate first. The options to authenticate can be found in the Authorization section.
I am going to use the header option for authorization purposes. In headers, we will create an object with Authorization key and will paste our access key, concatenating with 'Client-ID'. We have to add a params object with a key of query and the value will be 'flower'. So our componentDidMount method will look something like(paste your access key in the field of YOUR_ACCESS_KEY),
componentDidMount() {
    axios.get('https://api.unsplash.com/search/photos', {
        params: {
            query: 'flower'
        },
        headers: {
            Authorization: 'Client-ID YOUR_ACCESS_KEY'
        }
    });
}
If you want to look at what is happening, as we update the function. First, on your browser open developers' tools and click on the network section. Then press `ctrl + R` to record the reload. As you reload the page, you will see a field called `photos`. If you click on it, it will show you a set of fields. If you see that, congrats, we have covered a huge task.
Now we need to extract that info and have to use it to render a list of images. But a new problem is in there. We have to wait until the network request returns the data. After that, we are going to render the ImageList. This can be covered using async and await syntax. we will use async before the componentDidMount and await before the axios.get and will save it in a variable called 'response'. All we need to do is destructure the response to get the targeted value. For us, the targeted value is 'result'. As we get the value, we have to update the state using setState function. Now we have a list of images to render.we will pass this list as a prop to the ImageList component. The final look of our App.js will be,
import React from 'react';
import axios from 'axios';
import ImageList from './ImageList';

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {imageList: []}
    }
    async componentDidMount() {
        const response =  await axios.get('https://api.unsplash.com/search/photos', {
            params: {
                query: 'flower'
            },
            headers: {
                Authorization: 'Client-ID YOUR_ACCESS_KEY'
            }
        });
        this.setState({ imageList: response.data.results });
        console.log(this.state.imageList)
    }
    render() {
        return(
            <div className="container mt-4">
                <ImageList images={ this.state.imageList }/>    
            </div>
        );
    }
}

export default App;
We have to accept the props in our ImageList component as an argument. Destructure a prop makes it easy to access. Now, all we need to do is decorate the page. You can do it based on your preferences. I leaving it as simple as possible. The outcome of the ImageList container will look something like this,
import React from 'react';

const ImageList = ({ images }) => {
    console.log(images);
    if(images.length > 0) {
        return (
            <div className="row">
                {images.map(element => {
                    return(
                        <img src={element.urls.small} alt="..."  style={{maxHeight: "180px"}} className="col-sm-4 img-thumbnail"></img>
                    );
                })}
            </div>
        );
    }
    return <div className="bg-warning text-center">Not Image to show</div>;
};

export default ImageList;
If you follow all the instructions properly you will see a page similar to
Awesome, we have completed the task that we took as our mission. A long journey, from fetching data to render images on the page.
Well playing with API in React is not a difficult job. Whatever the API or the task you need to cover the basic flow to play with data is similar. The more we can divide our task into smaller milestones it becomes easier.

Written by Shakhawat-Hossain | I am a Full Stack developer, experience with building websites and web applications.
Published by HackerNoon on 2020/12/16