How to Render a List with React, GraphQL, and Apollo
By: Cristian Salcescu
Tags: JavaScript, React, Programming, Front End Development, GraphQL

In this article, we are going to take a look at how to retrieve and display a list of objects using React Hooks, GraphQL, and Apollo client.

List Function Component

Let’s start by displaying a list of objects using a React function component.

import React from 'react'; function List({posts}) {

return (

<div>

{posts.map(post =>

<div key={post.id}>

{post.title}

</div>

)}

</div>

);

} export default List;

The List function component takes a list of post objects and displays the title of each post in a div element.

In the App parent component, a hardcoded list is created and sent to the List function component.

import React from 'react';

import List from './List'; const posts = [

{ id: 1, title: "Lorem Ipsum" },

{ id: 2, title: "Sic Dolor amet" }

]; function App() {

return (

<div>

<List posts = {posts} />

</div>

);

} export default App;

That’s all we needed. We managed to define a hardcoded list of objects and then render that list using React.

GraphQL

Now let’s move further and take this list from a backend API. As discussed we will use a GraphQL API instead of a REST API.

Create Fake API

We are going to use json-graphql-server to create a fake GraphQL API on the fly.

Create a db.js file with the following GraphQL scheme definition.

module.exports = {

posts: [

{ id: 1, title: "Lorem Ipsum", views: 254, user_id: 123 },

{ id: 2, title: "Sic Dolor amet", views: 65, user_id: 456 }

],

users: [

{ id: 123, name: "John Doe" },

{ id: 456, name: "Jane Doe" }

],

comments: [

{ id: 987,

post_id: 1,

body: "Consectetur adipiscing elit",

date: new Date('2017-07-03')

},

{ id: 995,

post_id: 1,

body: "Nam molestie pellentesque dui",

date: new Date('2017-08-17') }

]

}

Then start the API using the json-graphql-server db.js — p 3001 command. At this point, the API is available at http://localhost:3001/ .

Access Fake API

Next, we will create an API utility function getAllPosts() that retrieves all the posts from the API.

We call the backend API using the axios library.

import axios from 'axios'; const axiosGQL = axios.create({

baseURL: 'http://localhost:3001/'

});



const Get_All_Posts_Query = `

{

allPosts {

id

title

views

}

}

`; function getAllPosts() {

return axiosGQL

.post('', { query: Get_All_Posts_Query })

.then(getData)

.then(data => data.allPosts);

}; function getData(response){

return response.data.data;

} export default { getAllPosts };

The Get_All_Posts_Query constant defines the GraphQL query to retrieve all the posts. It specifies that we want to retrieve all posts and that for each post we need the id , title , and the number of views .

Render the list

We can make the API call inside the App parent component using the useEffect React hook.

The useEffect hook allows us to execute a side-effect operation like retrieving data from and API after the component was rendered. Once the list is retrieved from the server it is saved as a local state.

The local state is defined using the useState hook. Initially, the state is just an empty list. When the list is retrieved from the backend API, the state is updated using setPosts function.

Once we have the list we sent it to the List component.

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

import List from './List';

import api from './api'; function App() {

const [posts, setPosts] = useState([]); useEffect(()=> {

api.getAllPosts()

.then(setPosts);

},[]) return (

<div>

<List posts = {posts} />

</div>

);

} export default App;

Apollo

Next, let’s make the API using the Apollo Client which provides a better integration to the GraphQL API.

Start by installing it.

npm install @apollo/client --save

Then we create the Apollo Client and use it to make the API call.

import { ApolloClient, InMemoryCache, gql } from '@apollo/client'; const client = new ApolloClient({

uri: 'http://localhost:3001/',

cache: new InMemoryCache()

});



const Get_All_Posts_Query = `

{

allPosts {

id

title

views

}

}

`; function getAllPosts() {

return client

.query({

query: gql`${Get_All_Posts_Query}`

})

.then(getData)

.then(data => data.allPosts);

}; function getData(response){

return response.data;

} export default { getAllPosts };

As we can see, there is not much difference from Axios API call.

useQuery Hook

Next, we are going to simplify the API integration by using the useQuery hook provided by the Apollo library.

This time we just keep the definition of the GraphQL query in the API file.

import { gql } from '@apollo/client';



const Get_All_Posts_Query = gql`

{

allPosts {

id

title

views

}

}

`; export { Get_All_Posts_Query };

In the App parent component we execute the API query using the useQuery hook.

As you can see, we make the API call by passing a GraphQL query string to the useQuery hook. The hook returns an object containing the loading , error , and data properties.

The loading property is used to display a loading message when necessary.

The error property is used to display an error message when needed.

The data retrieved from the server stays in the data property.

import React from 'react';

import { useQuery } from '@apollo/client';

import { Get_All_Posts_Query} from './api';

import List from './List'; function App() {

const { loading, error, data } = useQuery(Get_All_Posts_Query); if (loading) return (<p>Loading...</p>);

if (error) return (<p>Error : {error.message}</p>); return (

<div>

<List posts = {data.allPosts} />

</div>

);

} export default App;

Material UI

Next, we will improve the layout using the Material UI components.

npm install @material-ui/core

We can modify the select query to retrieve some more information like the user name.

import { gql } from '@apollo/client';



const Get_All_Posts_Query = gql`

{

allPosts {

id

title

views,

User {

name

}

}

}

`; export { Get_All_Posts_Query };

Then we can use the Material UI List components to display our data.

import React from 'react';

import List from '@material-ui/core/List';

import ListItem from '@material-ui/core/ListItem';

import ListItemText from '@material-ui/core/ListItemText';

import Divider from '@material-ui/core/Divider'; function PostList({posts}) {

return (

<div>

<List component="nav">

{posts.map(post =>

<React.Fragment>

<ListItem button>

<ListItemText secondary={post.User.name} />

<ListItemText primary={post.title} />

<ListItemText primary={post.views} />

</ListItem>

<Divider />

</React.Fragment>

)}

</List>

</div>

);

} export default PostList;

Recap

List components can be defined in React as functions returning an HTML representation of it.

GraphQL provides an alternative way of building APIs. The result is retrieved from the API by sending GraphQL queries. The API calls can be done by making POST calls to the API and sending the GraphQL queries.

The useQuery hook from the Apollo library provides a nicer way of executing GraphQL queries.

The source code is available on github.