Skip to main content

Client data fetching

Because a Gatsby site hydrates into a React app after loading statically, Gatsby is not just for static sites. You can fetch data dynamically on the client, as needed, as you would with any other React app.

To illustrate this, we’ll walk through a small example site that uses both Gatsby’s data layer at build-time and data on the client at run-time. This example is based loosely on Jason Lengstorf’s Gatsby with Apollo example. We’ll be fetching character data for Rick (of Rick and Morty) and a random pupper image.

Note: Check out the full example here, if helpful.

1. Create a Gatsby page component

No data yet. Just the basic React page that we’ll be populating.

index.js
import React, { Component } from "react"
import { graphql } from "gatsby"

class ClientFetchingExample extends Component {
  render() {
    return (
      <div style={{ textAlign: "center", width: "600px", margin: "50px auto" }}>
        <h1>Image of Rick</h1>
        <p>This will come from a build time query</p>

        <h2>Image of Rick's pupper</h2>
        <p>This will come from a request on the client</p>
      </div>
    )
  }
}

export default ClientFetchingExample

2. Query for character info at build time

To query for Rick’s character info and image, we’ll use the gatsby-source-graphql plugin. This will allow us to query the Rick and Morty API using Gatsby queries.

Note: To learn more about using gatsby-source-graphql, or about Gatsby’s GraphQL data layer, check out their respective docs. The purpose of including it here is only for comparison.

gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-graphql",
      options: {
        typeName: "RMAPI",
        fieldName: "rickAndMorty",
        url: "https://rickandmortyapi-gql.now.sh/",
      },
    },
  ],
}

Now we can add the query to our index.js page:

index.js
import React, { Component } from "react"
import { graphql } from "gatsby"

// This query is executed at build time by Gatsby.export const GatsbyQuery = graphql`  {    rickAndMorty {      character(id: 1) {        name        image      }    }  }`
class ClientFetchingExample extends Component {
  render() {
    const {      rickAndMorty: { character },    } = this.props.data
    return (
      <div style={{ textAlign: "center", width: "600px", margin: "50px auto" }}>
        <h1>{character.name} With His Pupper</h1>        <p>Rick & Morty API data loads at build time.</p>        <div>          <img            src={character.image}            alt={character.name}            style={{ width: 300 }}          />        </div>        <h2>Image of Rick's pupper</h2>
        <p>This will come from a request on the client</p>
      </div>
    )
  }
}

export default ClientFetchingExample

3. Fetch pupper info and image data on the client

Now we’ll finish out by fetching pupper info from the Dog CEO Dog API. (We’ll fetch a random pupper. Rick isn’t picky.)

index.js
import React, { Component } from "react"
import { graphql } from "gatsby"
import axios from "axios"
// This query is executed at build time by Gatsby.
export const GatsbyQuery = graphql`
  {
    rickAndMorty {
      character(id: 1) {
        name
        image
      }
    }
  }
`

class ClientFetchingExample extends Component {
  state = {    loading: false,    error: false,    pupper: {      img: "",      breed: "",    },  }
  componentDidMount() {    this.fetchRicksPupper()  }
  render() {
    const {
      rickAndMorty: { character },
    } = this.props.data

    const { img, breed } = this.state.pupper
    return (
      <div style={{ textAlign: "center", width: "600px", margin: "50px auto" }}>
        <h1>{character.name} With His Pupper</h1>
        <p>Rick & Morty API data loads at build time.</p>
        <p>Dog API data loads at run time.</p>        <div>
          <img
            src={character.image}
            alt={character.name}
            style={{ width: 300 }}
          />
        </div>
        <div>          {this.state.loading ? (            <p>Please hold, pupper incoming!</p>          ) : img && breed ? (            <>              <h2>{`${breed} pupper!`}</h2>              <img src={img} alt={`cute random `} style={{ maxWidth: 300 }} />            </>          ) : (            <p>Oh noes, error fetching pupper :(</p>          )}        </div>    )
  }

  fetchRicksPupper = () => {    this.setState({ loading: true })    axios      .get(`https://dog.ceo/api/breeds/image/random`)      .then(pupper => {        const {          data: { message: img },        } = pupper        const breed = img.split("/")[4]        this.setState({          loading: false,          pupper: {            ...this.state.pupper,            img,            breed,          },        })      })      .catch(error => {        this.setState({ loading: false, error })      })  }
export default ClientFetchingExample

That’s it — an example of querying for data at build time using the Gatsby GraphQL data layer and dynamically requesting data on the client at run time.

Other resources

You may be interested to check out other projects (both used in production and proof of concepts) that illustrate this usage:


Edit this page on GitHub
Docs
Tutorials
Plugins
Blog
Showcase