GraphQL Cheat Sheet
===================
### Overview
* An alternative approach to RESTful APIs
* Clients issue queries/mutations to read and update data
* Clients can fetch only the entity fields that are required
* GraphQL query syntax can express complex entity relations => nested objects
* Mitigates the explosion of RESTful endpoints in scenarios where many different representations of an entity are needed
* Graphiql is a query execution UI, also provides good documentation
### Express Server Integration
```javascript
const express = require('express');
const expressGraphQL = require('express-graphql');
const schema = require('./schema/schema');
// create express app
const app = express();
app.use('/graphql', expressGraphQL({
schema,
graphiql: true
}));
// register app to listen on a port
app.listen(4000, () => {
console.log('Server started!');
});
```
### Schema Types
* GraphQL Schema types define the data contract between the client and the server
```javascript
const GraphQL = require('graphql');
const {
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLList,
GraphQLSchema,
GraphQLNonNull
} = GraphQL;
// define the company schema type
const CompanyType = new GraphQLObjectType({
name: 'Company',
// use a closure to work around cyclical references
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString },
description: { type: GraphQLString },
users: {
type: new GraphQLList(UserType),
resolve(parentValue, args){
return axios.get(`http://localhost:3000/companies/${parentValue.id}/users`)
.then(resp => resp.data);
}
}
})
});
// define the user schema type
const UserType = new GraphQLObjectType({
name: 'User',
// use a closure to work around cyclical references
fields: () => ({
id: { type: GraphQLString },
firstName: { type: GraphQLString },
age: { type: GraphQLInt },
company: {
type: CompanyType,
resolve(parentValue, args) {
return axios.get(`http://localhost:3000/companies/${parentValue.companyId}`)
.then(resp => resp.data);
}
}
})
});
```
### Root Query Type
```javascript
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
user: {
type: UserType,
args: { id: { type: GraphQLString }},
resolve(parentValue, args) {
return [];
}
},
company: {
type: CompanyType,
args: { id: { type: GraphQLString }},
resolve(parentValue, args) {
// async promise
return axios.get(`http://localhost:3000/companies/${args.id}`)
.then(resp => resp.data);
}
}
}
});
```
### Root Mutation Type
```javascript
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addUser: {
type: UserType,
args: {
firstName: { type: new GraphQLNonNull(GraphQLString) },
age: { type: new GraphQLNonNull(GraphQLInt) },
companyId: { type: GraphQLString }
},
resolve(parentValue, { firstName, age }) {
return axios.post(`http://localhost:3000/users`, {
firstName,
age
}).then(res => res.data);
}
},
editUser: {
type: UserType,
args: {
id: { type: new GraphQLNonNull(GraphQLString) },
firstName: { type: GraphQLString },
age: { type: GraphQLInt },
companyId: { type: GraphQLString }
},
resolve(parentValue, { id, firstName, age, companyId }) {
var updatedUser = { firstName, age, companyId };
return axios.patch(`http://localhost:3000/users/${id}`, updatedUser)
.then(res => res.data);
}
}
}
});
```
### GraphQL Query Syntax
Simple Query:
```
query {
user(id: "40"){
id
firstName
age
}
}
```
Query With Relations:
```
query {
user(id: "40"){
id
firstName
age
company {
id,
name,
description
}
}
}
```
Query Fragments:
```
query findCompanyUsers {
apple: company(id:"1"){
...companyDetails
}
google: company(id:"2"){
...companyDetails
}
}
fragment companyDetails on Company {
id
name
description
users {
id
firstName
age
}
}
```
Parameterized Queries:
```
query UserQuery($id: ID!){
song(id: $id){
id
firstName
email
}
}
```
Parameter Values:
```javascript
{
"id": 12345
}
```
Mutation:
```
mutation {
addUser(firstName: "Jeff", age: 34){
id
firstName
age
}
}
```
### GraphQL Clients
* Lokka - Simple implementation: basic queries, mutations, and simple caching
* Apollo Client - Good balance between features and complexity
* Relay - Amazing performance on mobile, but the most complex.
### Apollo Client Initialization
Configuring a basic GraphQL client:
```javascript
// ...
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
// tracks objects by the ID field
const client = new ApolloClient({
dataIdFromObject: object => object.id
});
const Root = () => {
return (
Hello, {this.props.data.name}
); } } const currentUser = gql` query { currentUser { id firstName email } } `; // funky syntax, but this binds the query to the component props export default graphql(userQuery)(HelloGraphQL); ``` An alternative syntax: ```javascript // ... // this reads a little better const withData = graphql(userQuery); export default withData(HelloGraphQL); ``` ### React Components with GraphQL Mutations An example of a basic mutation: ```javascript import React, { Component } from 'react'; import gql from 'graphql-tag'; import ListUsers from '../queries/ListUsers'; class MutationExample extends Component { onDeleteUser(){ const id = 123; this.props.mutate({ variables: { id } }) .then(() => this.props.data.refetch()); }; } render(){ return (