Recently while teaching, I started to compile a list of "day to day" activities that a React developer would do. One common activity is integrating a component with an api. This consists of making a request to an external api and displaying the data. As a bonus, I would add a element to interact and change parameters sending to this api.
With this in mind, this article will cover a simple step by step plan that can be repeated to practice this daily activity in preparation for working as a React Developer.
The first step is to select an api and preview it's contents.
To select an api for practice, I'd recommend this list of public apis on Github.
https://github.com/public-api-lists/public-api-lists
The next step is to preview the api. For this example, we will use the Meowfacts api: https://github.com/wh-iterabb-it/meowfacts.
When previewing the api, we can make GET requests in our browser or use something like Hopscotch.io or Postman. (I use hopscotch since it is open source).
From the github page, there is one link: https://meowfacts.herokuapp.com/, so opening that in the browser, we can see the following.
And in Hopscotch, we make a GET request as well.
If you don't have a react app set up already, let's create one. In your normal work environment, this will be created for you usually.
npx create-react-app api-example
Now install and start the app.
cd api-example
npm start
The order doesn't necessarily matter, but for the next step I like to add a hard coded response then mock up the UI around it. Pulling from Hopscotch, we can use the following as an example response.
{
"data": [
"There are cats who have survived falls from over 32 stories (320 meters) onto concrete."
]
}
Open up a component. If you are following along, open up App.js. Let's add the response as a hard coded variable inside the App component. I also removed some of the boilerplate html.
function App() {
const catResponse = {
data: [
"There are cats who have survived falls from over 32 stories (320 meters) onto concrete."
]
}
return (
<div className="App">
</div>
);
}
Now we can use the variable to render the response. For this we can just use a simple un ordered list element. We will also use a React code block {}
to interpolate our variable into the html.
function App() {
const catResponse = {
data: [
"There are cats who have survived falls from over 32 stories (320 meters) onto concrete."
]
}
return (
<div className="App">
<ul>
<li>{catResponse.data[0]}</li>
</ul>
</div>
);
}
This is good so far, but let's take it one step further. The data
property is an array, so we can expect more facts to be in that array. Because of that, let's convert our html to use map
to render our lists. Note that I leave the verbose syntax to be a little easier for newer js devs to read.
function App() {
const catResponse = {
data: [
"There are cats who have survived falls from over 32 stories (320 meters) onto concrete."
]
}
return (
<div className="App">
<ul>
{catResponse.data.map((fact) => {
return (
<li>{fact}</li>
)
})}
</ul>
</div>
);
}
Now that we are rendering the response, we want to convert this to a state variable. In the end, we will make a request and update our variable. To do this, we need to add in the useState
hook.
The new line of code is this:
const [catResponse, setCatReaspon] = useState({})
Here we call React's useState
function and pass an empty object as our initial state. UseState will return an array with the first item being the state and the second being a function to change the state. So catResponse
will be empty.
To make this slightly better, we can use our hard coded response as the initial state. We can move the response out of the component and rename it initialState
than pass it to the useState
function. Then, when a user loads the page, they will see a fact while they wait for the api call. The final code looks like this.
import { useState } from 'react';
import './App.css';
const initialCatResponse = {
data: [
"There are cats who have survived falls from over 32 stories (320 meters) onto concrete."
]
}
function App() {
const [catResponse, setCatResponse] = useState(initialCatResponse)
return (
<div className="App">
<ul>
{catResponse.data.map((fact) => {
return (
<li>{fact}</li>
)
})}
</ul>
</div>
);
}
export default App;
We can now move on to making the api request. For this, we will use the fetch
api. The following is the function we will use for making the GET request to MeowFacts. Read more on the fetch api here if you are not familiar: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch.
async function getMeowFacts() {
const response = await fetch('https://meowfacts.herokuapp.com/')
const data = await response.json()
return data;
}
And finally, we can now get the response and update our state. To do this, we will use the useEffect
hook which allows for "side effects" in our app. It is commonly used on Component render to load api data. Some examples in w3schools are a nice explanation: https://www.w3schools.com/react/react_useeffect.asp.
We will use useEffect
with no dependencies for now to do a one time load and call our getMeowFacts
function. We also await the promise using then
syntax as React recommends useEffect
to be synchronous. Finally, we call the setCatReason
method from useState
to update our response. The following is the result.
useEffect(() => {
getMeowFacts().then((meowFactData) => {
setCatReason(meowFactData)
})
}, [])
The final code is the following which will be a familiar setup in your day to day React development.
import { useState, useEffect } from 'react';
import './App.css';
const initialCatResponse = {
data: [
"There are cats who have survived falls from over 32 stories (320 meters) onto concrete."
]
}
async function getMeowFacts() {
const response = await fetch('https://meowfacts.herokuapp.com/')
const data = await response.json()
return data;
}
function App() {
const [catResponse, setCatReason] = useState(initialCatResponse)
useEffect(() => {
getMeowFacts().then((meowFactData) => {
setCatReason(meowFactData)
})
}, [])
return (
<div className="App">
<h1>Meow Facts</h1>
<ul>
{catResponse.data.map((fact) => {
return (
<li>{fact}</li>
)
})}
</ul>
</div>
);
}
export default App;
The web page looks pretty bare bones, but styling is a separate article.