I got stuck for a few days learning about fetching API with React. Finally, I did it! If you struggle with fetching data with React hooks too, I hope this article can help you out.
Without further ado, let's dive right in.
React hooks
Okay, so what do we need to fetch API data in React?
Only two things:
React.useState
React.useEffect
These are React hooks to manage state and perform side effect of a component.
useState
React.useState hook is used to manage state of a variable. It looks something like this:
const [count, setCount] = React.useState(0)
The
count
variable is initalized with 0. To change this state, you have to set up the functionsetCount
and trigger it.
An example for setting state to add count:
import "React" from "react"
export default function Count() {
const [count, setCount] = React.useState(0)
function setCount() {
prevCount => prevCount + 1
}
return (
<div>
<p>{count}</p>
<button onClick={setCount}>Add</p>
</div>
)
}
Now every time, you click the Add button, the number will be increase by 1.
React useState* can manage all sorts of variable - a string, array, boolean, number, etc.
useEffect
React.useEffect allows you to perform any side effect of the components. For example, fetching API or save things to LocalStorage.
All you need to do is to wrap useEffect around a function you like to perform:
React.useEffect(() => {
// Run something
})
A funny thing is if you let it on like this the effect will run on forever. For example, in case you fetch an API, it will keep loading new data even if you don't refresh the site.
To have the function run once or on trigger, you need to add a dependency inside an array after the curly brace of your function.
React.useEffect(() => {
// Run only one time
}, [])
An empty array will run the function only once.
React.useEffect(() => {
// Run as value changes
}, [props or state value])
Adding props or state value inside the array will run the function as the value of the state change.
So that's it, you're packed with two powerful tools to fetch data from any API end points.
In this example, you will use the Harry Potter Movie API.
โก I solemnly swear that I'm up to no good.โก
Let's the code begin!
Basic set up
I use Scrimba online editor for this small project but you can install React to code in your local environment.
The basic set up include:
- index.js
- App.js
components/Movie.js
API fetching will take place in App.js
and components/Movie.js
.
First, create a component
folder and add a new file Movie.js
.
import React from "react"
export default function Movie() {
return (
<h1>Hello World</h1>
)
}
Our code will change later but for now let add a simple H1 to test how it renders on the screen.
Next, import Movie.js
to App.js
.
In your App.js, create a movies
variable to contain the data you fetch from API.
const [movies, setMovies] = React.useState([])
movies
will have an inital state of an empty string.
To add data from an API end point to movies
, add the following code:
React.useEffect(() => {
fetch("https://potter-db-api.herokuapp.com/v1/movies")
.then(res => res.json())
.then(data => setMovies(data.data))
}, [])
useEffect will handle any side effect from fetching API data from API. Once data is fetched, it will be saved to
movies
throughsetMovies
function. In other words,movies
state will change from empty array to an array of data from API.We use an empty array [] to fetch the data just once.
Now to render the data you've saved, map over the array movies
and indicate where it should display:
(still inside App function)
const MovieElements = movies.map(movie => {
return (
<Movie key={movie.id} movie={movie} />
)
return (
<div>
{MovieElements}
</div>
)
Over in the Movie.js
file, pass in the props and add the data you want to render. In this example, I will add the movie title, summary, and trailer link.
To see what data you can display, include a
console.log(movies)
inside your App function orconsole.log(data)
inside API fetching function.
Here's my code in components/Movie.js:
export default function Movie(props) {
return (
<div>
<img width="100px" />
<h3>{props.movie.attributes.title}</h3>
<p>{props.movie.attributes.summary}</p>
<a href={props.movie.attributes.trailer}>View trailer</a>
</div>
)
}
That's it. Now you will have a list of all movies in the data source.
| Link to example |
If you want to display only some movies, not the full list, use slice() to specific how many items you want to display
For example, this code will display only 5 Harry Potter movies on the page.
const movieElements = movies.slice(0, 5).map((item) => {
return <FilmItem key={item.id} film={item} />
});
Another thing you might want to do is to limit the number of words in longer texts like a summary.
All you need to do is to use .split(" ")
with spacing between "" to split words, then splice(0, 30)
to get 30 words, then join them again with join(" ")
.
<p>{props.movie.attributes.summary.split(" ").splice(0, 30).join(" ")}...<p>
I hope you'll find this article helpful. If you have some feedback, just drop a comment below or send me a note via Twitter. I'm easily reachable at @naomipham_.
Thank you for reading, and happy coding!
Top comments (6)
Well done putting it together, also thanks for the Harry Potter's API cause i'm big fan
Thank you! Haha me too Ahmed. Forever Potterhead!
awesome post!
Thanks so much, Carlos! ๐งก๐งก๐งก
Awesome work