Simple GraphQL & React Example

Simple GraphQL & React Example

This GraphQL React example is the bare minimum it takes to get an application up and running. It consists of just two files (with dependencies) both under 100 lines each.

These two files will show you start to finish how to make a GraphQL server and connect a React.js front-end to it.

It's the simplest example of the entire GraphQL React lifecycle I could come up with.

Setup

git clone git@github.com:tylerbuchea/simple-graphql-and-react-example.git
cd simple-graphql-and-react-example
yarn install
node server.js # Node v10 or later

GraphQL - server.js

This file contains the GraphQL schema and resolvers all wrapped up into one simple express server. For more advanced applications you would break this file up into parts.

const express = require('express');
const expressGraphQL = require('express-graphql');
const { buildSchema } = require('graphql');

// Setup
const app = new express();
const db = {
  users: [{ name: 'Tyler' }, { name: 'Brett' }, { name: 'Josh' }],
};

// GraphQL stuff
const resolvers = {
  users: () => {
    const { users } = db;
    return users;
  },
  createUser: ({ name }) => {
    const user = { name };
    db.users.push(user);
    return user;
  },
};

const schema = buildSchema(`
  type Query {
    users: [User]
  }
  type Mutation {
    createUser(name: String): User
  }
  type User {
    name: String
  }
`);

// Express stuff
app
  .use('/', express.static(__dirname + '/dist'))
  .use(
    '/graphql',
    expressGraphQL({
      schema,
      rootValue: resolvers,
      graphiql: true,
    })
  )
  .listen(3000, () => {
    console.log('Visit: http://localhost:3000/ for React.js front-end');
    console.log(
      'Visit: http://localhost:3000/graphql for GraphiQL'
    );
  });

React - src/index.js

I've put the React app and the GraphQL connection/queries into one file for clarities sake. If you want you can break the two sections up into separate files.

import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient from 'apollo-boost';
import { ApolloProvider, Query, Mutation } from 'react-apollo';
import gql from 'graphql-tag';

const client = new ApolloClient({ uri: 'http://localhost:3000/graphql' });
const CREATE_USER = gql(`
  mutation createUser($name: String) {
    createUser(name: $name) {
      name
    }
  }
`);
const GET_USERS = gql(`
  query getUsers {
    users {
      name
    }
  }
`);

class UserList extends React.Component {
  state = { name: '' };

  createUserHandler = (cache, { data: { createUser } }) => {
    const { users } = cache.readQuery({ query: GET_USERS });
    cache.writeQuery({
      query: GET_USERS,
      data: { users: users.concat([createUser]) },
    });
  };

  renderSubmitButton = createUser => (
    <button
      onClick={() => createUser({ variables: { name: this.state.name } })}
    >
      Create
    </button>
  );

  renderContent = ({ loading, error, data }) => {
    if (loading) return <h2>Loading...</h2>;
    if (error) return <h2>Error</h2>;
    return (
      <div>
        <h2>User List</h2>
        <input
          onChange={ev => this.setState({ name: ev.target.value })}
          placeholder="New username..."
          value={this.state.name}
        />
        <Mutation mutation={CREATE_USER} update={this.createUserHandler}>
          {this.renderSubmitButton}
        </Mutation>
        <ul>
          {data.users.map((user, index) => (
            <li key={index}>{user.name}</li>
          ))}
        </ul>
      </div>
    );
  };

  render() {
    return <Query query={GET_USERS}>{this.renderContent}</Query>;
  }
}

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