DEV Community

Naomi Pham
Naomi Pham

Posted on

How to fetch data from an API with React useState and useEffect

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) 
Enter fullscreen mode Exit fullscreen mode

The count variable is initalized with 0. To change this state, you have to set up the function setCount 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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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 
})
Enter fullscreen mode Exit fullscreen mode

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 
}, [])
Enter fullscreen mode Exit fullscreen mode

An empty array will run the function only once.

React.useEffect(() => {
    // Run as value changes 
}, [props or state value])
Enter fullscreen mode Exit fullscreen mode

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:

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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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([])

Enter fullscreen mode Exit fullscreen mode

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))
    }, [])

Enter fullscreen mode Exit fullscreen mode

useEffect will handle any side effect from fetching API data from API. Once data is fetched, it will be saved to movies through setMovies 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>
)
Enter fullscreen mode Exit fullscreen mode

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 or console.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>
    )
}
Enter fullscreen mode Exit fullscreen mode

That's it. Now you will have a list of all movies in the data source.

api-react
| 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} />
    });

Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
aradwan20 profile image
Ahmed Radwan

Well done putting it together, also thanks for the Harry Potter's API cause i'm big fan

Collapse
 
naomipham_ profile image
Naomi Pham

Thank you! Haha me too Ahmed. Forever Potterhead!

Collapse
 
carlosjuniordev profile image
Carlos Junior

awesome post!

Collapse
 
naomipham_ profile image
Naomi Pham

Thanks so much, Carlos! ๐Ÿงก๐Ÿงก๐Ÿงก

Collapse
 
darabgif profile image
Darab

Awesome work