Your First React GraphQL Frontend with the Apollo Client: A Gentle Introduction
Tags: react, javascript, webdev, graphql
Published: 2021-02-23 11:46:16

---
title: "Your First React GraphQL Frontend with the Apollo Client: A Gentle Introduction"
published: true
description: In this post, we'll create a React project from scratch using create-react-app, add in the Apollo GraphQL client, and then use the SpaceX GraphQL API to display data in our application.
tags: react, javascript, webdev, graphql
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rti8stb2ggwaw13bmjlk.png
canonical_url: https://typeofnan.dev/adding-apollo-graphql-to-your-react-project/
---

If you're integrating your React frontend with a GraphQL API, you may want to check out the Apollo client! I found it to be pretty straightforward to hook up.

In this post, we'll create a React project from scratch using `create-react-app`, add in the Apollo GraphQL client, and then use the SpaceX GraphQL API to display data in our application.

<hr />

### Please give this post a 💓, 🦄, and 🔖 if you want more introduction to GraphQL posts!

<hr />

# Creating a new React App

I'm going to use the `yarn` package manager to create a new React app called `react-with-apollo`. You can, of course, use `npm` if you'd like.

```bash
yarn create react-app react-with-apollo
```

We can `cd` into that directory and run `yarn start` to make sure our default React app is up-and-running on port 3000.

```bash
cd react-with-apollo
yarn start
```

If we navigate to http://localhost:3000, we'll get something like this:

![default React app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6op2wr3aucehwfp8rend.png)

# Adding GraphQL the Apollo Client

To use GraphQL with the Apollo client, we need to install them both as project dependencies. Let's do that with yarn.

```bash
yarn add graphql @apollo/client
```

The next thing we need to do is configure out Apollo client. Normally this might require figuring out authentication with your GraphQL server but, since the SpaceX API is public, we don't need to worry about that. Instead, we just need to configure the client with our GraphQL API endpoint. We can additionally specify any _caching_ we want to do for our queries. In this basic example, we'll just do some in-memory caching.

In this example, we'll configure our client in our `index.js` file and wrap our `App` in the Apollo provider. In practice you should probably put your Apollo provider as the lowest common ancestor for any components that will need to fetch data from the GraphQL API.

**index.html**

```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://api.spacex.land/graphql/',
  cache: new InMemoryCache(),
});

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

# Querying the API

We're now all set up to query the API! In our `App.js` file, let's create a query that gets past SpaceX missions, including the date, launch site, and rocket. Of course, since this is GraphQL, it's trivial to grab all that information in one query.

We will include one variable in our query, `numLaunches`, just so we can see how to use variables.

**App.js**

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

const PAST_LAUNCHES = gql`
  query GetPastLaunces($numLaunches: Int!) {
    launchesPast(limit: $numLaunches) {
      mission_name
      launch_date_local
      launch_site {
        site_name_long
      }
      rocket {
        rocket_name
      }
    }
  }
`;

function App() {
  // TBD
}
```

Now comes the part where we integrate the Apollo client. It has an incredibly handy `useQuery` hook that does a lot of heavy lifting for us. Basically, we pass the query we just defined, and any query options (in our case, just variables), and the hook returns a `loading` boolean, possibly an `error` object, and the returned `data`.

```jsx
import { gql, useQuery } from '@apollo/client';

const PAST_LAUNCHES = gql`
  query GetPastLaunces($numLaunches: Int!) {
    launchesPast(limit: $numLaunches) {
      mission_name
      launch_date_local
      launch_site {
        site_name_long
      }
      rocket {
        rocket_name
      }
    }
  }
`;

function App() {
  const { loading, error, data } = useQuery(PAST_LAUNCHES, {
    variables: {
      numLaunches: 10,
    },
  });
}
```

Here we can see that we have provided our `PAST_LAUNCHES` query along with our `numLaunches` parameter, which we have set for `10` right now.

So&mdash;let's use the information the hook is returning to us! Since we're just learning now we'll have a very simple interaction. If `loading` is `true`, we'll show the user a "Loading..." message, if `error` is truthy, we'll tell the user something has gone wrong, and otherwise we'll format our query data in a readable way.

```jsx
import { gql, useQuery } from '@apollo/client';

const PAST_LAUNCHES = gql`
  query GetPastLaunces($numLaunches: Int!) {
    launchesPast(limit: $numLaunches) {
      mission_name
      launch_date_local
      launch_site {
        site_name_long
      }
      rocket {
        rocket_name
      }
    }
  }
`;

function App() {
  const { loading, error, data } = useQuery(PAST_LAUNCHES, {
    variables: {
      numLaunches: 10,
    },
  });

  if (loading) {
    return <p>Loading...</p>;
  }

  if (error) {
    return <p>Oh no!</p>;
  }

  return (
    <ul>
      {data.launchesPast.map((launch) => (
        <li key={launch.mission_name}>
          <strong>{launch.mission_name}</strong>
          <ul>
            <li>
              Launch Date:{' '}
              {new Date(launch.launch_date_local).toLocaleDateString()}
            </li>
            <li>Rocket: {launch.rocket.rocket_name}</li>
            <li>Launch Site: {launch.launch_site.site_name_long}</li>
          </ul>
        </li>
      ))}
    </ul>
  );
}

export default App;
```

Of course, the structure of our `data` is exactly the same as the structure of our input query; one of the more helpful GraphQL features!

Let's check out our web app and see if things look alright.

![SpaceX launch data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uj8pef49atmpfq2u761m.png)

Perfect! Looks great to me.

# Updating Variables

In the last part of this post, let's explore how easy it is to re-fetch data if we update our variables. In this case, we may want a different number of past launches.

Our hope might be that we can just maintain a separate `numLaunches` stateful variable and, when we update that, we can cause te `useQuery` hook to fire again. In the following example, we just add a button to show five launches instead of 10. Trivial, but you get the idea!

```jsx
import { gql, useQuery } from '@apollo/client';
import { useState } from 'react';

const PAST_LAUNCHES = gql`
  query GetPastLaunces($numLaunches: Int!) {
    launchesPast(limit: $numLaunches) {
      mission_name
      launch_date_local
      launch_site {
        site_name_long
      }
      rocket {
        rocket_name
      }
    }
  }
`;

function App() {
  const [numLaunches, setNumLaunches] = useState(10);
  const { loading, error, data } = useQuery(PAST_LAUNCHES, {
    variables: {
      numLaunches,
    },
  });

  if (loading) {
    return <p>Loading...</p>;
  }

  if (error) {
    return <p>Oh no!</p>;
  }

  return (
    <>
      <button onClick={() => setNumLaunches(5)}>Show 5</button>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.mission_name}>
            <strong>{launch.mission_name}</strong>
            <ul>
              <li>
                Launch Date:{' '}
                {new Date(launch.launch_date_local).toLocaleDateString()}
              </li>
              <li>Rocket: {launch.rocket.rocket_name}</li>
              <li>Launch Site: {launch.launch_site.site_name_long}</li>
            </ul>
          </li>
        ))}
      </ul>
    </>
  );
}

export default App;
```

So does this work? Let's test it out.

![showing five results](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mos0pi37zgwq9hosg4sg.gif)

You bet it does!

# Concluding Thoughts

I'm enjoying the Apollo client with React quite a bit! It "just works" and offers the reactivity I need when executing GraphQL queries. Hopefully this post has helped you get started with GraphQL in React as well!