Let's build a contact list using React Hooks, function components, and a real API
Tags: webdev, codenewbie, react, beginners
Published: 2020-05-16 12:45:39

---
title: Let's build a contact list using React Hooks, function components, and a real API
published: true
description: Learn the basics of React, some modern features such as hooks, by building a contact list app!
tags: 
  - webdev
  - codenewbie
  - react
  - beginners
canonical_url: https://jschris.com/getting-started-with-react
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/bqm0tbeyjly6dgl1bpaf.png
---

So you want to learn React eh? This guide will walk through everything you need to know when getting started with React. We'll get set up, explain the "hows and whys" behind the basic concepts, and build a small project which pulls data from an API to see everything in action.

This will be a long one, so skip/re-read sections as you need using the "Jump to Section" links below. With that out of the way, grab a drink, buckle up, and let's get started.

> [This was originally posted on my new blog where I will be writing loads of JavaScript and React tutorials. Make sure to stop by www.jschris.com and say hello!](https://www.jschris.com)

## Jump to Section

* [Development Environment](#development-environment)
  * [Node.js](#node.js)
  * [VS Code](#visual-studio-code)
* [Creating a React App](#creating-a-react-app)
* [Lets Build a Contacts List!](#lets-build-a-contacts-list)
  * [Get the Styles](#get-the-styles)
  * [Creating the Contact Card](#creating-the-contact-card)
  * [Making Our Contact Card Reusable](#making-our-contact-card-reusable)
  * [Lets talk about State](#lets-talk-about-state---the-usestate-hook)
  * [Updating State](#updating-state)
  * [Introducing Props](#introducing-props)
  * [Using Props within a component](#using-props-within-a-component)
  * [Rendering components from a List](#rendering-components-from-a-list)
  * [Pulling data from an API](#pulling-data-from-an-api)
  * [Introducing useEffect](#introducing-useeffect)
* [Conclusion](#conclusion)


## Development Environment

The first thing we're going to do is set up a development environment. If you already setup **Node.js** and installed **Visual Studio Code** (or your preferred IDE), you can go ahead and skip to the next section [ADD LINK TO NEXT SECTION HERE]

### Node.js

[Go here and download](https://nodejs.org/en/download/) the right package for your OS (Mac/windows etc)

When the installation completes, open a terminal  and type this command: 

```js
node -v
```

This should show output the version of node you just installed:

![](https://jschris.com/static/75f85dfa0c07e6b38092fb8eb832a189/b5cea/node.png)

This means that the `node` command works and node has installed successfully - hurray! If you see any errors, try reinstalling Node from the package you downloaded and retry the command again.

### Visual Studio Code

Visual studio code is a popular open-source IDE that works well for frontend development. There are a bunch of others you can try - see what your favourite is and download that if you prefer. For now, we'll run with VS Code.

[Click here and download](https://code.visualstudio.com/download) the version for your platform: 

Follow the installation steps, and you should be good to go. Go ahead and fire up Visual Studio Code.

That's enough development setup for now. There are other nice things you can install (VS Code extensions etc) but we don't need those right now -We're here to learn React!

## Creating a React App

The next step is to create a React project. Lucky for us, the fine folk at Facebook have made this really simple. All we have to do is run a command within our terminal:

```jsx
npx create-react-app my-app
```

This creates a project for us called "my-app" and sets everything up automatically. Pretty cool.

Go ahead and open up a terminal in the directory you want to create your app, e.g a "projects" folder, and run the command. Let the terminal do its thing, and after a while, this will complete and show you some commands:

![](https://jschris.com/static/9d651a0597f10abac0a8687011b437f1/78363/cra-install.png)

Notice the **create-react-app** output has told us what we need to do to start the app. Go ahead and run the commands in your terminal:

```
cd my-app
yarn start
```

This will start a development server and open up a web browser for you:

![](https://jschris.com/static/a1a4aeb3c265e6753ce67bb5e9c66fe0/cb922/cra-start.png)

You've just set up your first React App! If you want to learn more about what's going on, (check out the "create-react-app" GitHub:)[https://github.com/facebook/create-react-app]



##  Lets Build a Contacts List! 

Our contacts list will display a number of a contacts, including their name, email, age and avatar (or, profile image).
We’ll build this up gradually, eventually pulling data from an API. How exciting! 
  
![](https://jschris.com/static/093da2b0c6947b52d83b42183d172718/6569d/contacts-list-intro.png)

## Get the styles

Since this is a React tutorial, we’re going to focus on the inner workings of React and not worry about creating nice styles. In your source folder, create a new file `styles.css` and paste in the following code:

```css
.contact-card {
  display: flex;
  padding: 10px;
  color: #ffffff;
  background-color: rgb(42, 84, 104);
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  box-shadow: 10px 10px 25px -16px rgba(0, 0, 0, 0.75);
  border-radius: 10px;
  max-width: 500px;
  max-height: 125px;
  margin-bottom: 10px;
}

.contact-card p {
  margin-left: 10px;
  margin-top: 0;
}

button {
  margin-left: 10px;
  margin-bottom: 10px;
}
```

Next, go into **App.js** and import the stylesheet like so:

```jsx
import "./styles.css";
```
 
## Creating the Contact Card

While we’re still in **App.js**,  let’s add the basic JSX to get our layout for the contact card in place. Remove everything from the **return** statement and add the following:

```jsx 
<div className="contact-card">
	<img src="https://via.placeholder.com/150" alt="profile" />
	<div className="user-details">
		<p>Name: Jenny Han</p>
		<p>Email: Jenny.Han@notreal.com</p>
		<p>Age: 25</p>
	</div>
</div>
```

All we’re doing here is creating a **div** to “wrap” the contact card details, adding an image (the image will use a placeholder taken from the web for now), and adding a few **p** tags to hold the details we need in the contact card. Finally we’re adding some **CSS classes** taken from `styles.css`;

> NOTE: to reference CSS classes, we need to use the **className** keyword. This is because we are writing JSX, and “class” is a reserved word in JavaScript.

Here’s what we have so far in our **App.js** file:

```jsx
import React from "react";
import "./styles.css";

const App = () => {
  return (
    <div className="contact-card">
      <img src="https://via.placeholder.com/150" alt="profile" />
      <div className="user-details">
        <p>Name: Jenny Han</p>
        <p>Email: Jenny.Han@notreal.com</p>
        <p>Age: 25</p>
      </div>
    </div>
  );
}
```

If you run this in the browser, you should see something similar to the following:

![](https://jschris.com/static/adff13952d09891bcb6c1d1c7a694bb9/89048/contac-card-template.png)

## Making our Contact Card Reusable 

OK so we have our contact card! However it’s not very reusable. We know that we are going to need to **reuse this code** if we want to render more than one card, so it makes sense to break this out **into it’s own component**

> NOTE - To make it easier to follow, I am going to a put all the components we make into **App.js** . In the real world it would be better to split these different components into their own files, and import/export them where appropriate.

Just beneath the **App** function, create a new function called **ContactCard**, and copy the JSX from **App** to  **ContactCard** like so:

```jsx
const ContactCard = () => {
  return (
    <div className="contact-card">
      <img src="https://via.placeholder.com/150" alt="profile" />
      <div className="user-details">
        <p>Name: Jenny Han</p>
        <p>Email: Jenny.Han@notreal.com</p>
        <p>Age: 25</p>
      </div>
    </div>
  );
};
```

Again, a component in React is just a **function that returns some JSX**.  Now that we’ve moved our JSX to the **ContactCard** we can use this component within our main**App component**:

```jsx
const App = () => {
  return (
    <>
      <ContactCard />
    </>
  );
}
```

We use our own components like any old HTML/JSX tag. We just put the **name of our component in angle brackets.** Our **App.js** file should look like this:

```jsx
// App.js
import React from "react";
import "./styles.css";

const App = () => {
  return (
    <>
      <ContactCard />
    </>
  );
};

const ContactCard = () => {
  return (
    <div className="contact-card">
      <img src="https://via.placeholder.com/150" alt="profile" />
      <div className="user-details">
        <p>Name: Jenny Han</p>
        <p>Email: Jenny.Han@notreal.com</p>
        <p>Age: 25</p>
      </div>
    </div>
  );
};
```

Now if you run this in the browser, things will look the same as they did before - which is what we want. We now have a **ContactCard** component that we can use as many times as we like:

```jsx
const App = () => {
  return (
    <>
      <ContactCard />
      <ContactCard />
      <ContactCard />
    </>
  );
};
```

Update the **App** component to include another 2 **ContactCard** components. The above example will render 3 contact cards in the browser. Go and check it out!

> Think of this like a “stamp” on the page. Every **ContactCard** component we add is another “stamp” and renders the same markup on the page

## Let’s talk about State - the useState Hook

If you’ve been getting started with React already, you may have heard of the term **state**. State is quite a big deal in React. So what is it?

> State is basically an object that represents a part of an app that can change, which the UI “reacts” to. State can be anything; objects, booleans, arrays, strings or integers 

Let’s take an example.

Some people who appear in our contact list are shy and do not want their age being displayed until a button is clicked. We can store **whether the age should be shown or not** in state by using the **useState hook within the component**. Which looks like this:

```jsx
const [showAge, setShowAge] = useState(false);
```

“what the hell is going on here?” Let me explain.

The **useState object** gives us a variable with the **current value**, and a function that **lets us change that value**. When we call **useState** we can define an **initial**value (in this case, **false**).

We use **destructuring assignment **on the **useState hook** to get these. You don’t have to worry about destructuring assignment right now, just remember that the first variable lets us access the state value, the second one lets us change it.

Go ahead and add the above code snippet to the**ContactCard** component like so:

```jsx
const ContactCard = () => {
  const [showAge, setShowAge] = useState(false);

  return (
    <div className="contact-card">
      <img src="https://via.placeholder.com/150" alt="profile" />
      <div className="user-details">
        <p>Name: Jenny Han</p>
        <p>Email: Jenny.Han@notreal.com</p>
        <p>Age: 25</p>
      </div>
    </div>
  );
};
```

Now we have a state object, how do we use it? Well, we can reference the `showAge` variable like any other variable. In this case, we want to _only show the age if the `showAge` variable is `true`. 

We can do this using the _ternary operator_ :

```jsx
{showAge === true ? <p>Age: 25</p> : null}
```

This example reads as _if the showAge variable is true, render the age, if not, render nothing_.

Go ahead and add this to the **ContactCard** component, like so:

```jsx
const ContactCard = () => {
  const [showAge, setShowAge] = useState(false);

  return (
    <div className="contact-card">
      <img src="https://via.placeholder.com/150" alt="profile" />
      <div className="user-details">
        <p>Name: Jenny Han</p>
        <p>Email: Jenny.Han@notreal.com</p>
        {showAge === true ? <p>Age: 25</p> : null}
      </div>
    </div>
  );
};
```

Now, if you run the app in the browser, you’ll see the **age** disappears - that’s because our `showAge` variable has been initialised with `false`. If we initialise our `showAge` variable with `true`:

```js
const [showAge, setShowAge] = useState(true);
```

The age will appear on the contact card. Nice! Although, its not great — we don’t want to change the code whenever we want to show the age on the contact card! 

Before we look at how to dynamically change our `showAge` variable, lets tidy the code a bit. Go ahead and replace this line:

```js
{showAge === true ? <p>Age: 25</p> : null}
```

With:

```js
{showAge && <p>Age: 25</p> }
```

This gives the same result, just in a more concise way.

> TIP: Shorten code where it makes sense to, don’t feel like you have to shorten every line of code you write! Readability should come first. 

## Updating State

Ok back to updating state. If we remember back, the `useState()` hook gives us a **function to update the state**. Let’s wire this up to a button, which, when clicked, will toggle showing the age on the contact card.

We can do this with the following:

```jsx
<button onClick={() => setShowAge(!showAge)}>
	Toggle Age 
</button>
```

What this is doing is calling the **setShowAge function** (which we get from the useState hook) to change the **value of show age to the opposite of what it currently is**.

> NOTE: I’m using the **Arrow Function** syntax here to pass a function to the `onClick` property. If you’re not familiar we this, a quick reminder that you can get my [book where I discuss the important bits of JavaScript to know before React here].

When the state updates, React will **re-render the component** and since the value of `showAge` is true, the age will be displayed. 

If the user clicks the button again, this will set `showAge` to `false`, React will re-render the component, and the age will be hidden:

![](https://jschris.com/46201add1931d222dde4782768435378/age-toggle.gif)

Look at our fancy toggle in action! 

> TIP: Whenever the components state changes, React will re-render the component with the new state

Notice how even though we have 3 **ContactCard** components being rendered, when we click the button the age only displays for **one** of the cards, and not all of them. This is because **state belongs to the individual component**. In other words, each **ContactCard** component that renders is a **copy**, and has its own state/data.


## Introducing Props

So now we have a lovely new **ContactCard** component that we’re reusing a few times. Although its not really reusable, since the name, email, age and avatar are the same for each of our components. Oh dear! We can make this data more dynamic with what are called **props**. 

Since you’re just getting started with React, you can think of**Props** as data that gets passed to a component, which the component can then use. For example, we can pass in our **avatar** , ** email**, **name** and **age** as props to our **Contact Card** component like so:

```jsx
<ContactCard
  avatar="https://via.placeholder.com/150"
  name="Jenny Han"
  email="jenny.han@notreal.com"
  age={25}
/>
```

As you can see, we define a prop by giving it a name. Eg. *name* and using the **equals** to assign some value to that prop e.g **Jenny Han**.

We can have as many props as we want, and we can name these props whatever we want, so they’re pretty flexible. 

Props can hold different types of data, i.e strings, numbers, booleans, objects, arrays and so on. 

> NOTE: Props must be defined using quoted text (e.g name=“Jenny Han”) or within braces (e.g `age={25}`. If we leave out the braces for anything other than strings things start to break - `age=25` );

Go ahead and replace the current**ContactCard** components within  our **App** component with the following:

```jsx
<ContactCard
  avatar="https://via.placeholder.com/150"
  name="Jenny Han"
  email="jenny.han@notreal.com"
  age={25}
/>

<ContactCard
  avatar="https://via.placeholder.com/150"
  name="Jason Long"
  email="jason.long@notreal.com"
  age={45}
/>

<ContactCard
  avatar="https://via.placeholder.com/150"
  name="Peter Pan"
  email="peter.pan@neverland.com"
  age={100}
/>
```

 
All we’re doing here is passing **the data that the component needs** to each component as props. Notice how the data is different for each component.

## Using Props within a component

We’ve sent a bunch of props down to the **ContactCard** component, so let’s tell the ** ContactCard** how to use them.

Until now, our ** ContactCard** function doesn’t accept any _parameters_. React, being the magical thing that it is, automatically puts all our props into a lovely **props object**, that gets passed into the component:

```jsx
const ContactCard = props => {
	//...other code
};
```

Notice the **props** variable. This is an object containing the props we defined previously.  We can _access our defined props_ by using the _dot notation_ like so:

```jsx
const ContactCard = props => {
	console.log(props.avatar); 
	console.log(props.name);
	console.log(props.email);
	console.log(props.age);

	//...other code
};
```

Finally, we want to replace the hardcoded values in our JSX, with the values we receive from the props:

```jsx
return (
  <div className="contact-card">
    <img src={props.avatar} alt="profile" />
    <div className="user-details">
      <p>Name: {props.name}</p>
      <p>Email: {props.email}</p>
      <button onClick={() => setShowAge(!showAge)}>Toggle Age </button>
      {showAge && <p>Age: {props.age}</p>}
    </div>
  </div>
);
```

Notice how we have set the **image source** using whatever value we received from props. We did similar for **name**, **email**, and **age**.  Also notice how we wrap this code in **curly braces**, so it gets executed as JavaScript.

Our final **App.js** file looks like this:

```jsx
// App.js
const App = () => {
  return (
    <>
      <ContactCard
        avatar="https://via.placeholder.com/150"
        name="Jenny Han"
        email="jenny.han@notreal.com"
        age={25}
      />
      <ContactCard
        avatar="https://via.placeholder.com/150"
        name="Jason Long"
        email="jason.long@notreal.com"
        age={45}
      />
      <ContactCard
        avatar="https://via.placeholder.com/150"
        name="Peter Pan"
        email="peter.pan@neverland.com"
        age={100}
      />
    </>
  );
};

const ContactCard = props => {
  const [showAge, setShowAge] = useState(false);

  return (
    <div className="contact-card">
      <img src={props.avatar} alt="profile" />
      <div className="user-details">
        <p>Name: {props.name}</p>
        <p>Email: {props.email}</p>
        <button onClick={() => setShowAge(!showAge)}>
			Toggle Age 
		</button>
        {showAge && <p>Age: {props.age}</p>}
      </div>
    </div>
  );
};
```

If you run this in the browser, you should see something similar to this:

![](https://jschris.com/static/a01167e9d19e96ec4689edbe74bfbdcc/d56e1/contact-lists-3-components.png)

Hurray! Our component works the same as before, but its now more dynamic. We can reuse the same **ContactCard** but passing in different data - whilst keeping the layout, styles, and state objects the same.

## Rendering components from a List

Our contacts list is coming along nicely, we have some well crafted, reusable code so time to leave it alone right? Wrong! Let’s take it a step further.

In a real application, data usually comes in the form of an array of data, e.g after an API call. Let’s pretend we’ve made an API call to **retrieve some users from a database** and have received the following data:

```js
const contacts = [
    { name: "Jenny Han", email: "jenny.han@notreal.com", age: 25 },
    { name: "Jason Long", email: "jason.long@notreal.com", age: 45 },
    { name: "Peter Pan", email: "peter.pan@neverland.com", age: 100 }
];
```

Paste this into the **App()** component at the top of the function. The eagled eye amongst you will notice how this data is similar to what we already have. But how we we turn this data into **ContactCard** components? Well, remember all those days you spent learning how to loop over an array using **.map()**? Now is the day we put that into action!

To display a list of components, we:

1) Loop over the array using **.map()**
2) For each item in the array, create a new **ContactCard component**
3) Pass the data from each object in the array to the **ContactCard component** as props

Let’s see how this works. In our app**App()** component, replace the **return** statement with this:

```jsx
return (
  <>
    {contacts.map(contact => (
      <ContactCard
        avatar="https://via.placeholder.com/150"
        name={contact.name}
        email={contact.email}
        age={contact.age}
      />
    ))}
  </>
);
```

As you can see, we **map over the array**. For each object in the array, we want to create a new **ContactCard** component. For the props, we want to take the **name**,  **email**, and **age** from the **current object the map function is on**. In other words, from the **contact** variable.

> NOTE: I’ve left the “avatar” prop alone, as this is the same for now - it’ll change later in the tutorial

And that’s it! Our **App.js** file looks like this:

```jsx
//App.js
const App = () => {
  const contacts = [
    { name: "Jenny Han", email: "jenny.han@notreal.com", age: 25 },
    { name: "Jason Long", email: "jason.long@notreal.com", age: 45 },
    { name: "Peter Pan", email: "peter.pan@neverland.com", age: 100 },
    { name: "Amy McDonald", email: "amy@email.com", age: 33 }
  ];

  return (
    <>
      {contacts.map(contact => (
        <ContactCard
          avatar="https://via.placeholder.com/150"
          name={contact.name}
          email={contact.email}
          age={contact.age}
        />
      ))}
    </>
  );
};
```

Run this in the browser and things should look the same. We haven’t change our **ContactCard**, merely changed where we got the data from. The cool thing about this is that if you added another row to the **contacts** array,  the extra component will get rendered automatically- you don’t have to do anything else! Try this for yourself and see.

## Pulling data from an API
We’ve got a nice looking React App now, nice and dynamic and things are working well. Which is a good place to be since we’re just getting started with React! But there are some tidy ups we need to make. In a real application, **data will be pulled in from an API**.

For the next part of the tutorial, we are going to get real contacts (when I say real contacts, I mean fake contacts - you know what I mean) from a real API: [https://randomuser.me/]. Feel free to browse the website and look at the response we will get back — this is where we will get our data to populate our components.

Firstly, let’s create a **state variable** to hold the data we get back from the API. Remember, state is good for holding that that can change. Our contacts list can definitely change!

In **App.js**, remove the **contacts** array add the following:

```js
const [contacts, setContacts] = useState([]);
```

Here, we’re doing here is creating a state object, and initialising it to an empty Array. When we make the API call, we’ll update the state to contain a list of contacts. Since we named this state object **contacts**, our rendering logic within the JSX will look for this array instead (as opposed to the old **contacts** array we just deleted).

Next, let’s grab the data from the API.  We’ll use the standard **Fetch API**. For now, we’ll log the data to the console. Add the following below the state object we just created:

```js
fetch("https://randomuser.me/api/?results=3")
  .then(response => response.json())
  .then(data => {
    console.log(data);
  });
```

All we’re doing here is:

- Making a GET request to the **randomuser** API, asking for **three** results
- Convert the response into **JSON**
- Logging the **JSON** to the console.

If you run this in the browser, you’ll notice the **ContactCard** components no longer render - thats fine, we haven’t saved any new data to state yet, and our state variable is currently empty. If you look at the console (in your browser dev tools) you’ll notice the response object is logged. Which will look something like this:

![](https://jschris.com/static/2327d21e950dd2b2d3a0c7c51fac655d/587b0/response_object.png)

You’ll see we have a **results** array, which has 3 objects. Each of these objects contain the details of a user (or a “Contact” in our case). This is similar to the **contacts** array we manually created ourselves in the previous section - just an array full of objects. 

Let’s update our **App** components JSX to pick data from this object. Update the JSX like so:

```jsx
return (
  <>
    {contacts.map(contact => (
      <ContactCard
        avatar={contact.picture.large}
        name={contact.name.first + " " + contact.name.last}
        email={contact.email}
        age={contact.dob.age}
      />
    ))}
  </>
);
```

This works similar to what we had before:

- We are looping through the **contacts** variable (which, at the moment is an empty array)
- When we eventually save the response to state (the next step) we look through each object in the array, for the appropriate things we need: in this case **picture, name, email, and dob** objects.  

Next we want to store the **results** array in state, so our JSX can loop over it (using the **map()** function we seen previously) and render some lovely **ContactCards**. Within our **fetch** function, add the call to **setContacts(data.results)** like so:

```jsx
fetch("https://randomuser.me/api/?results=3")
  .then(response => response.json())
  .then(data => {
    console.log(data);
    setContacts(data.results);
  });
```

Our **App** component now looks like this:

```jsx
//App.js
const App = () => {
  const [contacts, setContacts] = useState([]);

fetch("https://randomuser.me/api/?results=3")
  .then(response => response.json())
  .then(data => {
    console.log(data);
    setContacts(data.results);
  });

  return (
    <>
      {contacts.map(contact => (
        <ContactCard
          avatar={contact.picture.large}
          name={contact.name.first + " " + contact.name.last}
          email={contact.email}
          age={contact.dob.age}
        />
      ))}
    </>
  );
};
```

 If you save this, and run it in the browser, you’ll see something like this:

![](https://jschris.com/4bd02a07f80d45810780b5db77db42b3/multiple-calls-to-api.gif)

“WTF is going on everything is broken!”, don’t panic just yet (If you’re on a slower machine or just getting a bit freaked out, you can comment out the **setContacts(data.results)** line within the **fetch** function for now).

What’s happening here is that we’re stuck in a bit of a loop:

1) We make a call to **fetch** and get some data back 
2) We then **save this data to state**
3) Remember, React does a **re-render when the state changes**
4) When the component re-renders, the **fetch** api call happens again, and sets the state
5) Since the state updated, the component re-renders again
6) After the component re-renders, fetch is called again…
7) You get the idea

So how do we stop this? We have to delete everything and start again. Nah just kidding, don’t run away yet. We can fix this with another built in React Hook - **useEffect**.

## Introducing useEffect

The **useEffect** hook is a special hook that runs a function. By default, the useEffect hook runs on every re-render. However, we can configure it to only run **under certain condition**, e.g when a **component mounts**, or **if a variable changes**. The useEffect hook looks like this:

```js
useEffect(() => {
	// code to run 
});
```

This will run every time. If we want to specify **“only run once”** we pass in an **empty array** as a second argument like so. 

```js
useEffect(() => {
	// code to run 
},[]); //<-- notice the empty array
```

This is called a **dependency array**. When the dependency array is empty, this means the useEffect function will only run when the component loads for the first time. For additional re-renders, the useEffect function is skipped. 

This is a perfect place to put our API call, as we only want to get the data once, when the component loads. Go ahead and place a **useEffect()**function into our**App** component, and move the **fetch** API call into the useEffect function. Our  **App** component now looks like this:

```jsx
//App.js
const App = () => {
  const [contacts, setContacts] = useState([]);

  useEffect(() => {
    fetch("https://randomuser.me/api/?results=3")
      .then(response => response.json())
      .then(data => {
        setContacts(data.results);
      });
  }, []);

  return (
    <>
      {contacts.map(contact => (
        <ContactCard
          avatar={contact.picture.large}
          name={contact.name.first + " " + contact.name.last}
          email={contact.email}
          age={contact.dob.age}
        />
      ))}
    </>
  );
};
```

Now, if you run the code in your browser, you should see 3 contact cards appear! Refresh the page to see another randomised list of contacts:

![](https://jschris.com/static/093da2b0c6947b52d83b42183d172718/6569d/contacts-list-intro.png)

## Conclusion

Congrats! You just completed your first real-world app and laid the foundation to move onto more advanced topics. 

[Make sure to subscribe here to stay up to date with my latest React content, course discounts and early access, as well as some free stuff!](https://subscribe.jschris.com)