Updated with Hooks How To GraphQL with React Apollo
Tags: gql, graphql, react, apollo
Published: 2020-08-26 16:35:10

---
title: Updated with Hooks How To GraphQL with React Apollo
published: true
description: The [How To GraphQL](https://www.howtographql.com/react-apollo/0-introduction/) with React Apollo is quiet outdated. This is part 1 of the updated hooks version.
tags: #gql, #graphql, #react, #apollo
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/sshghryvi35zkwf6k9yc.png
canonical_url: https://console-logs.netlify.app/logs/graphql
---

Hi, I'm Brittney and I'm an instructor over at [ZTM Academy](https://academy.zerotomastery.io/?affcode=441520_gjue7n-1) and the owner, designer, and developer at [bDesigned](www.bdesigned.dev). You can find more dev notes by me at [Console Logs](https://console-logs.netlify.com/).

# How To GraphQL Updated Tutorial Part 1

## Table of Contents

- [Frontend Setup](#frontend-setup)
- [Into the code](#into-the-code)
  - [index.js](#indexjs)
  - [Server](#server)
  - [Frontend](#frontend)
  - [GraphQL Query](#graphql-query)
  - [Mutations](#mutations-1)
  - [React Router](#react-router)
  - [Header](#header)

---

TLDR: The [How To GraphQL](https://www.howtographql.com/react-apollo/0-introduction/) with React Apollo is quiet outdated. This is part 1 of the updated hooks version.

## Frontend Setup

- 1\. Create project


```bash
yarn create react-app hackernews-react-apollo
cd hackernews-react-apollo
```

- 2\. Add git origin

 
```git
git add remote origin URL
git add .
git commit -m 'init fresh repo'
git push --set-upstream origin master
```

- 3\. Restructure app

 
```bash
mkdir src/components src/styles
```

- 4\. Move `App.js` into components folder, then move index.css and App.css into styles folder.

<br/>

- 5\. Update imports.


```js
// index.js
import './styles/index.css';
import App from './components/App';
```

```js
// App.js
import logo from '../logo.svg';
import '../styles/App.css';
```

- 6\. Add tacheyons to `public/index.html`

 
```html
<!-- public/index.html under other links in head -->
<link rel="stylesheet" href="https://unpkg.com/tachyons@4.2.1/css/tachyons.min.css"/>
```

- 7\. Replace CSS in `index.css`


```css
/* index.css */
body {
  margin: 0;
  padding: 0;
  font-family: Verdana, Geneva, sans-serif;
}
input {
  max-width: 500px;
}
.gray {
  color: #828282;
}
.orange {
  background-color: #ff6600;
}
.background-gray {
  background-color: rgb(246,246,239);
}
.f11 {
  font-size: 11px;
}
.w85 {
  width: 85%;
}
.button {
  font-family: monospace;
  font-size: 10pt;
  color: black;
  background-color: buttonface;
  text-align: center;
  padding: 2px 6px 3px;
  border-width: 2px;
  border-style: outset;
  border-color: buttonface;
  cursor: pointer;
  max-width: 250px;
}
```

- 8\. Add Apollo and GraphQL packages

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

That's it for the setup, we are now ready to start writing some code.

---

### Into the code

#### index.js

- 1\. Add packages to `index.js`.


```js
import {
  createHttpLink,
  InMemoryCache,
  ApolloClient,
  ApolloProvider,
} from "@apollo/client";
```

- 2\. Create variables to connect ApolloClient.

 
```js
const httpLink = createHttpLink({
  uri: 'http://localhost:4000'
})
const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache()
})
```

- 3\. Change out wrapper component around `<App />` to the Apollo Provider.


```js
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
```

#### Server

The code to download the backend of the server was not correct on the tutorial. In order to get the correct version, I cloned the [React-Apollo Tutorial Repo](https://github.com/howtographql/react-apollo). Then, I copied the **server** folder and pasted it into the root of my project. This will add a directory called server to your application. Inside there are prisma files to connect to the database and inside the src folder is the GraphQL server files. We now need to deploy the Prisma database so the GraphQL server can access it.

```bash
cd server
yarn install prisma1 global
yarn install
prisma1 deploy
```

After running **`prisma1 deploy`** navigate to Demo server + MySQL database, hit enter and then choose the location closest to you to create your database. Next, we need to run our backend locally. While still in the server directory run **`yarn start`** and leave it running. Now we can run two mutations to check our connection to the database. Navigate to [http://localhost:4000/](http://localhost:4000/) and paste in the following mutations.

```graphql
mutation CreatePrismaLink {
  post(
    description: "Prisma turns your database into a GraphQL API 😎",
    url: "https://www.prismagraphql.com"
  ) {
    id
  }
}

mutation CreateApolloLink {
  post(
    description: "The best GraphQL client for React",
    url: "https://www.apollographql.com/docs/react/"
  ) {
    id
  }
}
```

Press the play button and select each mutation once. It should return an id. If this worked, we can verify the links were added by running the following query.

```graphql
{
  feed {
    links {
      id
      description
      url
    }
  }
}
```

It should return the json data with the id, description, and url of the 2 links.

#### Frontend

Now that the backend is working, we can implement the client side of the application. First, we are going to display a list of **Link** elements. Inside of the components directory, create a file named **`Link.js`** and add the following code to it.

```jsx
import React from 'react'

const Link = (props) => {
  const link = props.link
  return (
    <div>
      {link.description} ({link.url})
    </div>
  )
}

export default Link
```

This is a React component that is being passed **props** and then displaying the links from those props. Now we can create the component that will list the links. Add a new file in the components directory called **`LinkList.js`** and put the following code inside. For now, we will just hard-code some data do display.

```jsx
import React from 'react'
import Link from './Link'

const ListLinks = () => {
  const links = [
    {
      id: '1',
      description: 'Prisma turns your database into a GraphQL API 😎',
      url: 'https://www.prismagraphql.com',
    },
    {
      id: '2',
      description: 'The best GraphQL client',
      url: 'https://www.apollographql.com/docs/react/',
    },
  ]
  return (
    <div>
      {links.map(link => <Link key={link.id} link={link} />)}
    </div>
  )
}

export default ListLinks
```

Now to see the changes, we need to go to **`App.js`** and change the contents to the following.

```jsx
import React from 'react';
import ListLinks from './ListLinks'
import '../styles/App.css';

function App() {
  return (
    <div className="App">
      <ListLinks />
    </div>
  );
}

export default App;
```

Now if we run **`yarn start`** from the root directory, we should see the 2 links displayed on the screen.

#### GraphQL Query

Next, we'll need to actually query the database for the links stored so they are dynamic instead of hard-coded in. Head to **`LinkList.js`** and we are going to change a few things.

- 1\. Import new packages
 
```jsx
import gql from 'graphql-tag'
import { useQuery } from '@apollo/client'
```

- 2\. Underneath the imports add in **LINK_QUERY** and remove hard-coded links.
 
```jsx
// export to be used later and create query for links
export const LINK_QUERY = gql`
{
  feed {
    links {
      id
      url
      description
    }
  }
}
`
```

- 3\. Destructure off the **useQuery** hook and update the return statement.
 
```jsx
const ListLinks = () => {
  const { loading, error, data } = useQuery(LINK_QUERY)
  return (
    <>
    {/* IF LOADING */}
      {loading && <div>Fetching...</div>}
    {/* IF ERROR */}
      {error && <div>There was an error fetching the data.</div>}
    {/* ELSE RETURN DATA FROM QUERY */}
      {data && (
        <div>{data.feed.links.map(link =>
          <Link key={link.id} link={link} />
        )}
        </div>
      )}
    </>
  )
}
```

If this worked correctly, we should now have a page that has different states able to be seen on the screen. One while loading, one if there is an error, and the list of links being returned.

#### Mutations

To add new links to our list we need to add a new file in our components folder called **`CreateLink.js`** that includes the following code.

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

const LINK_MUTATION = gql`
  mutation PostMutation($description: String!, $url: String!) {
    post(description: $description, url: $url) {
      id
      url
      description
    }
  }
`

const CreateLink = () => {
  const [description, setDescription] = useState("")
  const [url, setUrl] = useState("")

  const [createLink] = useMutation(LINK_MUTATION)

  return (
    <div>
      <div className="flex flex-column mt3">
        <input
          className="mb2"
          value={description}
          onChange={e => setDescription(e.target.value)}
          type="text"
          placeholder="A description for the link"
        />
        <input
          className="mb2"
          value={url}
          onChange={e => setUrl(e.target.value)}
          type="text"
          placeholder="The URL for the link"
        />
      </div>
      <button
        onClick={() => {
          createLink({
            variables: {
              description,
              url
            }
          })
        }}
      >
        Submit
        </button>
    </div>
  )
}

export default CreateLink
```

This file includes the import to use gql and the useMutation hook, the GraphQL mutation, and some state to handle updating the url and description of the link. This can be tested by adding the component into **`App.js`** below **`<ListLinks />`** component.

```jsx
import React from 'react';
import ListLinks from './ListLinks'
import CreateLink from './CreateLink';
import '../styles/App.css';

function App() {
  return (
    <div className="App">
      <ListLinks />
      <CreateLink />
    </div>
  );
}

export default App;
```

To actually see the update, the page needs to be refreshed or queried in the playground. To avoid this, we can add in React Router to the application to refresh the page.

#### React Router

Make sure you are in the root directory of the application and run the following command.

```bash
yarn add react-router react-router-dom
```

Now we need to add it to the application in **`index.js`**.Import **`react-router-dom`** and wrap the **`ApolloProvider`** in the router. 

```jsx
import { BrowserRouter as Router } from 'react-router-dom'

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

#### Header

Now, lets create a Header component to hold the links. In the components folder create a new file called **`Header.js`**. The following code will import React and the Link component from react-router-dom and display a title and two links.

```jsx
import React from 'react'
import { Link } from 'react-router-dom'

const Header = () => {
  return (
    <div className="flex pa3 justify-between nowrap orange">
      <div className="fw7 mr1 black">Hacker News</div>
      <div className='flex'>
        <Link to="/" className="ml1 no-underline black">
          new
          </Link>
        <div className="ml1 white">|</div>
        <Link to="/create" className="ml1 no-underline black">
          submit
          </Link>
      </div>
    </div>
  )
}

export default Header
```

To see the header, we need to add it into **`App.js`**. We need to import the `Header` and the `Switch` and `Route` components from `react-router-dom`.

```jsx
// add these imports
import { Switch, Route } from 'react-router-dom'
import Header from './Header'

// update App component to the following
function App() {
  return (
    <div className="center w85">
      <Header />
      <div className="ph3 pv1 background-gray">
        <Switch>
          <Route exact path="/" component={ListLinks} />
          <Route exact path="/create" component={CreateLink} />
        </Switch>
      </div>
    </div>
  );
}
```

Last, we need to update the **`CreateLink`** component so the browser will go back to the list after submitting a new link.

```jsx
// add useHistory import and query to imports
import { LINK_QUERY } from './ListLinks'
import { useHistory } from "react-router-dom";

// initiate useHistory inside component
let history = useHistory();

// update cached links
  const updateCache = (cache, { data }) => {
    const currentLinksList = cache.readQuery({
      query: LINK_QUERY
    })
    const updatedLinksList = [...currentLinksList.feed.links, data.post]

    cache.writeQuery({
      query: LINK_QUERY,
      data: {
        feed: {
          __typename: "Feed",
          links: updatedLinksList,
          count: updatedLinksList.length
        }
      }
    })
  }

// update createLink variable
  const [createLink] = useMutation(LINK_MUTATION, {
    onCompleted: () => history.push("/"),
    onError: () => history.push("/"),
    update: updateCache
  });
```

Now, the list of links and the create new link are on separate pages. You should have a page that looks similar to this.

<p align="center">
<img alt="Hackernews Clone Page" src="https://dev-to-uploads.s3.amazonaws.com/i/ylsg26def6d8baea9dng.png" width="100%">
</p>