An Example API call in React

Let’s take a look at how to make a call to an API, store the response and render to a view.

We’ll start with our basic App.js script, I’ve stripped out everything we don’t need from scaffolding the app:

import React from 'react';

function App() {
  return (
    <div className="App">
      
    </div>
  );
}

export default App;

Because we’ll be setting the returned data to state within our app function, we need to import useState and useEffect:

import React, {useState, useEffect} from 'react';

Now we can define the state object within our function, we do this inside the App function but outside of the return method:

const [items, setItems] = useState([]);

Next we can make the call to an API, I’ve chosen an open fortnite API as its free and very easy to use, if we refer to the documentation here, and look through the list to find the API for the shop, we are given a URL:

https://fortnite-api.com/v2/cosmetics/br

When we visit the URL we can see the data that is returned:

At first glance it can look confusing but this will make more sense when we display it with some structure within our app.

Making the API call

A moment ago we added the items and setItems state objects to our code, underneath that code add the following:

const fetchItems = async () => {
  const data = await fetch('https://fortnite-api.com/v2/cosmetics/br')
  const items = await data.json();
}

First, we create an arrow function that we can call when an event takes place (fetchItems()) this could be on button press or when a component loads.

We use the property async in the function to tell react this is an asynchronous function, and to basically get on with other stuff until something happens.

We then declare a new variable ‘data’ where the response from the call will be stored, we use the await argument on the fetch call, which works in conjunction with the async property in the function call (just always use these together).

Then we create another new variable called ‘items’ and in it we’ll store the response body which we also parse as json.

To test all of this add a console.log to the fetchItems() function, which should look like this:

const fetchItems = async () => {
  const data = await fetch('https://fortnite-api.com/v2/cosmetics/br')
  const items = await data.json();
  console.log(items);
}

If you run the project you’ll get an empty page, what happened? We need to call the fetchItems() function when the app loads. This is where useEffect gets involved (remember we imported useEffect earlier).

At the very top of the App function add the following code:

useEffect(() => {
    fetchItems();
}, []);

When the component initially loads the fetchItems() function will run, getting the API data, parsing and json and logging to the console.

Start the project (npm start) and open a browser, take a look at the browser console:

Perfect! the status confirms a successful request. And an array of 4601 objects has been returned as data. However we need to drill down into the json to get the individual objects to save to our state.

We can see that the array is stored in an object called ‘data’ so we can append ‘items’ with ‘data’ in our console log to return only to array of objects we need:

const fetchItems = async () => {
  const data = await fetch('https://fortnite-api.com/v2/cosmetics/br')
  const items = await data.json();
  console.log(items.data);
}

Your browser should refresh, check the console again and we should see the list of objects:

Nice! Let’s store this massive array in our ‘items’ object in our state:

const fetchItems = async () => {
  const data = await fetch('https://fortnite-api.com/v2/cosmetics/br')
  const items = await data.json();
  console.log(items.data);
  setItems(items.data);
}

Now that we have the array of objects in our ‘terms’ state, we can iterate through them and extract some information to display on the page. To do this we need to add a .map() method to our return method in our App function. But before we do that we need to pick some information to display, expand the array of objects in the browser console:

From the list above we’ll use ‘name’ and one of the images to display on the page, this will be a great start!

return (
    <div className="App">
      {items.slice(0, 10).map(item => (
        <div>
          <h2>{item.name}</h2>
          <img src={item.images.smallIcon} />
        </div>
      ))}
    </div>
  );

Because of the huge number of total objects in the items array I’ve also limited the number we’ll be iterating through to only 10 using ‘items.slice(0, 10)’.

If we now refresh the page we should see 10 fortnite items rendered on the page:

That’s it!! We’ve made a call to an API, retrieved some data which we parsed as json, saved the array to state and iterated through it to render our selected info out to the browser.

Hold on John!

If you noticed this error in the console:

Then you caught me! However it is easily fixed, if we refer back to the object json one of the object attributes is ‘id’, which gives a unique id to every item returned. All we need to do is assign this value to the child element of the map function:

return (
    <div className="App">
      {items.slice(0, 10).map(item => (
        <div key={item.id}>
          <h2>{item.name}</h2>
          <img src={item.images.smallIcon} />
        </div>
      ))}
    </div>
  );

The final App.js file

import React, {useState, useEffect} from 'react';

function App() {

  useEffect(() => {
    fetchItems();
    // Adding the empty square brackets means this will run when the component mounts
  }, []);

  const [items, setItems] = useState([]);

  // Call to fetch the fortnite API
  const fetchItems = async () => {
    const data = await fetch('https://fortnite-api.com/v2/cosmetics/br');
    const items = await data.json();
    console.log(items.data)
    setItems(items.data);
  }

  return (
    <div className="App">
      {items.slice(0, 10).map(item => (
        <div key={item.id}>
          <h2>{item.name}</h2>
          <img src={item.images.smallIcon} />
        </div>
      ))}
    </div>
  );
}

export default App;