How to use GraphQL on the client using Apollo and on the server using Prisma

The Apollo platform helps you build, query, and manage a unified graph: a data layer that enables applications to interact with data from any combination of connected data stores and external APIs.

Your graph sits between application clients and back-end services, facilitating the flow of data between them.

Apollo is a client that let us handle global state.

Installing dependencies

yarn add apollo-boost react-apollo graphql

Here’s an overview of the packages you just installed:

How to use

We will use create-react-app and on the root we look for index.js file and add the client:

import React from "react";
import { render } from "react-dom";
import { ApolloClient } from "apollo-client";
import { ApolloProvider } from "react-apollo";
import { createHttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

const httpLink = createHttpLink({
  uri: "http://localhost:5000",
});

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: httpLink,
});

render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById("root")
);

It’s very similar to what we did with Redux and the Provider

How to do a Query

import gql from "graphql-tag";

export const GET_GAMES = gql`
  query getGames {
    allGames {
      title
      description
    }
  }
`;

How to CREATE

import gql from "graphql-tag";

export const CREATE_GAME = gql`
  mutation CreateGame($title: String!, $description: String!) {
    createGame(title: $title, description: $description) {
      title
      description
    }
  }
`;

How to UPDATE

import gql from "graphql-tag";

export const UPDATE_GAME = gql`
  mutation UpdateGame($id: ID!, $title: String!, $description: String!) {
    updateGame(id: $id, title: $title, description: $description) {
      id
      title
      description
    }
  }
`;

How to DELETE

import gql from "graphql-tag";

export const DELETE_GAME = gql`
  mutation DeleteGame($id: ID!) {
    deleteGame(id: $id) {
      id
    }
  }
`;

How to apply queries and mutations in code

READ

...
import { useQuery } from '@apollo/react-hooks'
...

const { loading, error, data } = useQuery(GET_GAMES)
if (loading) return <div>LOADING</div>
if (error) return <div>There was an error: {error}</div>
return (
  {data.map(o => (
    <div key={o.title}>{o.title}</div>
  ))}
)

CREATE

...
import { useMutation } from '@apollo/react-hooks'
...

const [title, setTitle] = useState('')
const [description, setDescription] = useState('')
const [createGame] = useMutation(CREATE_GAME, {
    refetchQueries: [ { query: GET_GAMES } ]
  })

const handleSubmit = () => {
  createGame({ variables: {title, description} })
}

return (
  <form onSubmit={handleSubmit}>
    <input type='text' value={title} onChange={e => setTitle(e.target.value)} />
    <input type='text' value={description} onChange={e => setDescription(e.target.value)} />
  </form>
)

We can perform similar codes for updating and deleting using the previous examples.

Starting from scratch

Installing dependencies

On the same project we worked on last post, write the following commands:

npx create-react-app client
cd client
yarn add apollo-boost react-apollo graphql

File Structure

Project/
├── src/
│   ├── App.js
│   └── App.css
└── index.js

Erase everything until it looks like this.

Now configure index.js with Apollo Provider and use the EP provided by Prisma.

Inside App.js import everything necesary to perform a GET request like this:

import React from "react";
import "./App.css";
import gql from "graphql-tag";
import { useQuery } from "@apollo/react-hooks";

const GET_DATA = gql`
  query getData {
    feed {
      id
      description
      url
    }
  }
`;

const App = () => {
  const { loading, error, data } = useQuery(GET_DATA);
  if (loading) return <div>LOADING</div>;
  if (error) return <div>There was an error: {error}</div>;
  console.log(data);
  return <div>Test</div>;
};

export default App;

Check your console and you will see the information you requested!

Now lets add a POST query from the client side.

import React from "react";
import "./App.css";
import gql from "graphql-tag";
import { useQuery, useMutation } from "@apollo/react-hooks";

const GET_DATA = gql`
  query getData {
    feed {
      id
      description
      url
    }
  }
`;

const CREATE_LINK = gql`
  mutation CreateLink($url: String!, $description: String!) {
    post(url: $url, description: $description) {
      url
      description
    }
  }
`;

const App = () => {
  const [url, setUrl] = useState("");
  const [description, setDescription] = useState("");
  const { loading, error, data } = useQuery(GET_DATA);
  const [createLink] = useMutation(CREATE_LINK, {
    refetchQueries: [
      {
        query: GET_DATA,
      },
    ],
  });
  if (loading) return <div>LOADING</div>;
  if (error) return <div>There was an error: {error}</div>;

  const onChange = (setter) => (e) => setter(e.target.value);
  const onSubmit = () => createLink({ variables: { url, description } });

  const createForm = (
    <form onSubmit={onSubmit}>
      <label>Url: </label>
      <input type="text" name="url" value={url} onChange={onChange(setUrl)} />
      <label>Description: </label>
      <input
        type="text"
        name="description"
        value={url}
        onChange={onChange(setUrl)}
      />

      <input type="submit" value="submit" />
    </form>
  );

  const information = (
    <ul>
      {data.feed.map((o) => (
        <li key={o.id}>
          URL: {o.url} | DESCRIPTION: {o.descriiption}
        </li>
      ))}
    </ul>
  );
  return (
    <div>
      {createForm}
      {information}
    </div>
  );
};

export default App;

And finally inside our index.js:

import React from "react";
import { render } from "react-dom";
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import { InMemoryCache } from "apollo-cache-inmemory";
import App from "./App";

const client = new ApolloClient({
  cache: new InMemoryCache(),
  // server url
  uri: "http://localhost:5000/",
});

render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById("root")
);

Summary

Conclusion

Today we learned how to use Apollo with React! Its very similar to the way we handle Redux, in the sense that we wrap our App with a provider which connects with the server, where we send queries and in the server we have the resolvers waiting to solve those queries and return the requested information.

We will be doing more projects related to GraphQL.

See you on the next post.

Sincerely,

Eng. Adrian Beria