react-logo

How to Connect your React App to a REST API

Hello again! Did you ever try to display data from a remote backend in your React app? In the third part of this article series, you will learn how to fetch data from a REST API and use it inside your app. 

In the previous parts of this series you learned how to bootstrap a new React app with create-react-app and create a list component. Today we are going to connect this app to an existing REST API and use the fetched data to display our previously created list of contacts.

Over the whole series of articles, we’re going to build a functional contact list with React:

Part 1 – How to Create a React App with create-react-app
Part 2 – How to Create a React List Component
Part 3 – How to Connect your React App to a REST API

Article Roadmap

In this article, you will learn

  • How to fetch data from a remote REST API
  • How to store fetched data in the State of a React component

We will adapt our App component from part 2. First, it will retrieve contact data from a remote API and stores it in it’s State. Then we will pass the data inside State to our ContactList components props. This way, the app fetches contacts at the startup and fills our contact list with data.

Preparations

If you don’t have the source code of the previous part ready, you can clone it from GitHub, install the dependencies and start the app

git clone https://github.com/areiterer/contacts-manager.git
cd contacts-manager
git checkout part-2
npm install
npm start

The app is now available at http://localhost:3000 in your browser and you should see where we’ve left off last time.

Fetching Data from a REST API

To fetch data from a REST API, you perform an AJAX request to a REST API which will return the requested information. There are several ways to fulfill this task. You could either do this the vanilla way by creating a XHRequest, or use some helper libraries to make things easier for you:

Those three are just the examples that came to my mind. If you do some research, you will stumble upon a lot more helper tools for AJAX requests.

In this article we’re going to use axios for our app. I’m not going to explain each of the listed tools, but feel free to use one of your own preference, if you want to. With React, you can use whatever library you want to fetch data from whichever backend. You’re not locked in to a certain toolset.

The following example shows, how you can perform an AJAX GET request with axios:

axios
  .get("https://jsonplaceholder.typicode.com/users")
  .then(function(response) {
    console.log(response);
  })
  .catch(function(error) {
    console.log(error);
  });

axios.get returns a Promise. That’s great, because you can chain functions to a Promise with .then. This means, everything you put into a .then that you chain to axios’ get function, will be executed after the data returned. We’ll need that later. Also, you can catch errors by chaining .catch to the call.

Handling State

Usually you want to store the data you fetched, for further usage. In React, you would do that in the Store of a component, so the app can react to the retrieved data.

We will choose the App component to do so, because it’s the root component of our ContactList component. So at startup, the App component will fetch the contact data from a server and stores it in it’s State. Because we will bind the props of ContactList to the State of App, the newly retrieved data will be passed, as soon as it is placed in the State.

I will describe how we store our stuff in the component’s State in the next section, so let’s get our hands dirty and work on our app!

Fetching Data into a React Component

Before we start, let’s talk about what we’re going to do and why.

Data is usually retrieved in a Lifecycle Method componentDidMount. At this point in the lifecycle of a React component, the component was already rendered and put into the DOM. Also, we have access to this.state which we need to store the received contact data.

This means, we’re going to perform our AJAX request to the server inside our componentDidMount lifecycle method. And as soon as we get the requested data back we set our State, which again triggers a re-render of our components because now they’ve got some data to show.

Also, I want to talk a bit about the REST API — the backend we’re going to use.

The Backend

For this app, we’re going to use an existing REST API to fetch our contact names: https://jsonplaceholder.typicode.com/users

If you visit the URL, you will see that it returns an array of users. For now, we’re taking the id and the name information to display our contact list.

But that’s enough talking for now, let’s finally begin!

Applying our Changes

As stated at the top of this article, we’re going to use axios to perform AJAX requests. To begin, let’s install axios: In your root directory (where your package.json is) execute the following command line:

npm i -S axios

Next, open your App.js and perform the following actions:

  • add the componentDidMount lifecycle method to the App component.
  • import axios from the just installed package
  • add the axios GET request to componentDidMount to retrieve the contact data and store it in the App component’s State.
  • bind the “contacts” prop of ComponentList to App component’s State to pass the contact data.

Here’s what your App.js should look like:

// ...
import axios from "axios";

class App extends Component {

  // default State object
  state = {
    contacts: []
  };

  componentDidMount() {
    axios
      .get("https://jsonplaceholder.typicode.com/users")
      .then(response => {

        // create an array of contacts only with relevant data
        const newContacts = response.data.map(c => {
          return {
            id: c.id,
            name: c.name
          };
        });

        // create a new "State" object without mutating 
        // the original State object. 
        const newState = Object.assign({}, this.state, {
          contacts: newContacts
        });

        // store the new state object in the component's state
        this.setState(newState);
      })
      .catch(error => console.log(error));
  }

  render() {
    return (
      <div className="App">
        
        ...

        <ContactList contacts={this.state.contacts} />
      </div>
    );
  }
}

export default App;

So what did we do? First, we added the componentDidMount lifecycle method to the App component.

Fetching the Data from a Rest API

We imported axios and performed an AJAX GET request to the REST API with axios.get(). Then we chain our “callback” with .then to the request, to execute our logic as soon as the data returns from the backend.

Use .map() to Pick Relevant Data

Like I told you before, we’re getting back way too much data for our use case, so we’re not going to store everything of that. With the help of map, we pick only the relevant data and put it into a new array of objects that only contain id and name of the returned contacts.

Use Object.assign to Merge new Data into the State Object

Then we create a new State object by using Object.assign(). That’s a way to make a copy of an object and alter it without mutating the original object. Note: NEVER modify the State object directly!

Let’s see what Object.assign does with our objects:

Object.assign({}, this.state, {contacts: newContacts});

The first argument: {} is the target object. All of the following objects are going to be merged together from right to left. So in our case, an object with a propery “contacts” (an array with our newContacts) will be merged into the current State object. Since there is already a “contacts” property, it will be overwritten by the content of the “contacts” property of the object next object. After that, the newly merged object is merged to the target object. Since it is empty, it is the initial State object with a replaced “contacts” property.

Finally – Set the new State

Now that we got our data, picked the relevant parts out of it and created a “new” State object, we store it in the State of the App component.

this.setState(newState)

This call, puts the “newState” object as our new State.

Note: You can also pass a function to setState. This is very important to know, because setState is asynchronous. So whenever you set your State depending on the current State of the application, pass a function to setState. Learn more about this in the React docs.

Passing the State Data to the ContactList

Instead of our static array of contact objects, we’re now able to bind our State to the ContactList element.

<ContactList contacts={this.state.contacts} />

By referencing this.state.contacts we make sure, that everytime the State changes, ContactList will get the new contacts array, which causes the contact list to be re-rendered.

Congratulations! You just connected your app to a remote REST API, fetched some data and stored it into the State.

Additional Exercise

Now that we retrieved contact data from a remote REST API, stored some data in our State and display it in a list of components by passing it down via props.

Your homework today will be to add some more fields to our Contact component. The REST backend we’re using returns a lot more data, so try to display also the email and the phone number of each contact in the list.

Wrapping Up

Today you’ve learned, that you can communicate with REST APIs by using tools like fetchaxios or superagent. Also, you learned that if you want to fetch data from a server at the startup of the app, you’ll do it in componentDidMount in a suitable component.

You also learned, how to set State and that you can pass an object or a function to setState.

Last but not least, you’ve learned that if you bind the State of a component to a prop of another component, it will automatically get the new data passed, every time the State changes.


Learn more about how to create a fully functional React app from start until the deployment in my upcoming ebook:

Leave a Reply

Your email address will not be published. Required fields are marked *