In Front-End Development - 6 months ago

GatsbyJS: Build a user listing web app. (Part 2)

In this article, we will learn how to pull data from an external api and structure the data with GraphQL.

Introduction

This was what we achieved in part 1 of the tutorial.

  1. Installed Node.js and npm
  2. Installed Git
  3. Created a GatsbyJS starter template

Pulling data from an external API

We will be requesting data from the Random User Generator's API.

To do that, we would need to install the gatsby-source-apiserver plugin and set the configuration options in a gatsby-config.js file.

  1. Open up the terminal and run the following command.
$ npm install --save gatsby-source-apiserver

 

  1. Create a gatsby-config.js file at the root folder.
$ touch gatsby-config.js

 

  1. Add the following code to gatsby-config.js.
module.exports = {
  plugins: [{
    resolve: 'gatsby-source-apiserver',
    options: {
      url: 'https://randomuser.me/api/',
      method: 'get',
      headers: {
        'Content-Type': 'application/json'
      },
      typePrefix: 'internal__',
      name: `posts`,
      params: {
        results: 10
      },
      verboseOutput: true,
    }
  }],
}

 

Let's go through the various options.

  • url: The endpoint of the API to pull the data from.
  • typePrefix and name: Identifiers for our JSON entity. The GraphQL query will return undefined if omitted.
  • params: Query parameters. In this example, we are requesting 10 results from the API.
  • verboseOutput: To generate the output when building our GatsbyJS Site. We use this for debugging purposes.

You can view the full option configurations from the plugin page.

What is gatsby-config.js used for?

The gatsby-config.js file stores plugin configurations and/or common pieces of data for code reuse throughout a GatsbyJS site.

See the GatsbyJS official documentation for details.

  1. Rebuild the site.
$ npm run develop

Structure our query with GraphiQL

As mentioned earlier, GatsbyJS leverages on GraphQL to build its data layer for query extraction and execution.

The graphical interactive in-browser IDE; GraphiQL; allows developers to easily explore and structure their queries.

To access the IDE, visit http://localhost:8000/___graphql from your browser.

The IDE provides two helpful keyboard shortcuts. CTRL+Space for autocompletion and CTRL+Enter to run the query.

Let's try a simple query. Type the following in the GraphiQL IDE.

query {

}

 

  1. Place the cursor between the two curly braces and hit CTRL+Space for the list of nodes.
  2. Select allInternalPosts. (Our plugin's typeprefix and name.)
  3. Hit CTRL+Enter to run the query.

GraphQL intelligently built the data schema by making connections to all internal__posts nodes.

Let's expand the query. We need the user's Name, Gender, Email, Contact No., Profile image and Address details.

  1. Move the cursor down to id and hit enter.
  2. Hit CTRL+Space for a new list of nodes.
  3. Select results and hit CTRL+Enter to run the query.
  4. Move the cursor down to nat and hit enter.
  5. Select location and hit CTRL+Enter to run the query.

 

With our structure ready, we can start to build the home page.

Open index.js and insert the following code.

import React from "react"
import { graphql } from "gatsby"

export const query = graphql`
query {
  allInternalPosts {
    edges {
      node {
        id
        results {
          name {
            title
            first
            last
          }
          gender
          email
          phone
          cell
          nat
          picture {
            large
            medium
            thumbnail
          }
          location {
            street
            city
            state
          }
        }
      }
    }
  }
}
`

export default ({ data }) => {
  return (
  <div>
  {data.allInternalPosts.edges.map(({ node }, ...index) => (
  <div key={index}>
    {node.results && node.results.map((data, ...index) => (
    <div key={index}>
      <ul>
        <li>{data.name.title} {data.name.first} {data.name.last}</li>
        <li>{data.gender}</li>
        <li>{data.email}</li>
        <li>{data.phone}</li>
        <li><img src={data.picture.thumbnail} alt={`${data.name.title} ${data.name.first} ${data.name.last}`} /></li>
      </ul>
    </div>
    ))}
  </div>
  ))}
</div>
  )
}

 

Save your file to see the populated data in the browser.

With HMR or Hot Module Replacement support in GatsbyJS, the browser refreshes and loads new data everytime we save our changes.

What happened?

We used GraphQL to pull data into our home page component.

We then used the JavaScript map() method to loop through the array and display the results on the page.

What is HMR?

Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running, without a full reload. This can significantly speed up development in a few ways:

  • Retain application state which is lost during a full reload.
  • Save valuable development time by only updating what's changed.
  • Modifications made to CSS/JS in the source code results in an instant browser update which is almost comparable to changing styles directly in the browser's dev tools.

https://webpack.js.org/concepts/hot-module-replacement/

User details page

Add a file inside src/pages and name it details.js.

$ touch src/pages/index.js

 

Paste the following code in details.js.

import React from "react"
import { Link } from "gatsby"

export default ({ location }) => {
const value = location.state.data
return (
<div>
  <img src={value.picture.large} alt={`${value.name.title} ${value.name.first} ${value.name.last}`} />
  <div>
    <h5>{value.name.title} {value.name.first} {value.name.last}</h5>
    <ul>
      <li><strong>Gender:</strong> {value.gender}</li>
      <li><strong>Email:</strong> {value.email}</li>
      <li><strong>Address:</strong> {value.location.street}, {value.location.city}, {value.location.state}</li>
    </ul>
  </div>
  <div>
    <Link to="/">Back to Home</Link>
  </div>
</div>
)}

 

Add a link to the details page in index.js.

import React from "react"
import { graphql, Link } from "gatsby"


...img src={data.picture.thumbnail} alt={`${data.name.title} ${data.name.first} ${data.name.last}`} /></li>
        <li><Link
          to={`/details/`}
          state={{data}}
        >View Details</Link></li>
...

 

We include a GatsbyJS Link component in both index.js and details.js to link internal pages within our site.

To pass user data from the source page to the linked page, we passed data prop in the location state.

Thereafter, we can use the passed data as a nested object structure with the location prop in details.js.

GatsbyJS components

Our pages are getting chunky. Let's refactor the code.

Create a new src/components folder and add a new file profile.js inside it.

$ mkdir ./src/components && touch ./src/components/profile.js

 

Add the following code to profile.js.

import React from "react"
import { Link } from "gatsby"

export default ({props}, index) => {
  return (
    <ul>
      <li>{props.name.title} {props.name.first} {props.name.last}</li>
      <li>{props.gender}</li>
      <li>{props.email}</li>
      <li>{props.phone}</li>
      <li><img src={props.picture.thumbnail} alt={`${props.name.title} ${props.name.first} ${props.name.last}`} /></li>
      <li><Link
        to={`/details/`}
        state={{props}}
      >View Details</Link></li>
    </ul>
  )
}

 

Edit index.js with the following.

...
import { graphql } from "gatsby"
import Profile from "../components/profile.js"

...
export default ({ data }) => {
  return (
  <div>
  {data.allInternalPosts.edges.map(({ node }, ...index) => (
  <div key={index}>
    {node.results && node.results.map((data, ...index) => (
    <div key={index}>
      <Profile props={data} />
    </div>
    ))}
  </div>
  ))}
</div>
  )
}

 

Change the value of location.state.data to location.state.props in details.js.

...
export default ({ location }) => {
const value = location.state.props
return (
...

 

Our page still works. The main difference is that we split the code into smaller manageable components.

The application is still missing an important feature. Search.

In part 3, we will integrate a search feature to our application using JS Search and Axios.


blog comments powered by Disqus