Unleashing the power of GraphQL
slides.com/gerardsans | @gerardsans

Google Developer Expert

Master of Ceremonies




















Blogger
GraphQL

GraphQL co-authors



Lee Byron
Nick Schrock
Dan Schafer
GraphQL Timeline
2012
GraphQL created at Facebook
Support Mobile Native Teams

2016
GitHub announces GraphQL API
New GraphQL website
First GraphQL Summit
GraphQL First
2017
GraphQL Europe
Apollo Client 0.10.0 (RC-0)

graphql.org

Apollo Optics

May
graphql-europe.org
Speakers


Lee Byron
Sashko Stubailo
Implementations










Query Language
// GET '/graphql'
{
user(name: "gsans") {
twitter
}
}
// result
{
"user": {
"twitter": "@gerardsans"
}
}
GraphQL Server

source: blog
Who is using it?





Solution Architecture

demo
Components Tree
<app>
<add-todo>
<input><button>Add todo</button>
</add-todo>
<todo-list>
<ul>
<todo id="0" completed="false"><li>buy milk</li></todo>
</ul>
</todo-list>
<filters>
Show: <filter-link><a>All</a><filter-link> ...
</filters>
</app>
GraphQL Schema
Type System
- Scalar Types: Int, Float, String, Boolean, ID
- Object Types: Todo
- Entry points: Query, Mutation, Subscription*
Schema Syntax
- Nullable: String, Todo
- Non-nullable: String!, Todo!
- Arrays: [String], [Todo]

Todos Schema (1/2)
schema {
query: Query,
mutation: Mutation
}
type Query {
allTodoes(skip: Int, take: Int): [Todo!]!
}
type Todo {
id: ID!
text: String!
complete: Boolean!
}
Todos Schema (2/2)
schema {
query: Query,
mutation: Mutation
}
type Mutation {
createTodo(text: String!, complete: Boolean!): Todo
updateTodo(id: ID!, text: String, complete: Boolean): Todo
}

GraphiQL
demo


Apollo Client
GraphQL Server

source: blog
Dependencies
- JavaScript client for GraphQL (apollo-client)
- Analyses queries and results to keep data cached
- API to run queries and mutations (react-apollo)
- Template literal (graphql-tag)
Setup
// client.js
import ApolloClient, { createNetworkInterface } from 'apollo-client'
const networkInterface = createNetworkInterface({
uri: 'https://api.graph.cool',
dataIdFromObject: record => record.id, // will be used by caching
})
export const client = new ApolloClient({ networkInterface })
Todo App
// TodoApp.js
class TodoApp extends React.Component {
render () {
return (
<div>
<AddTodo addTodo={this.props.addTodo} />
<TodoList
todos={this.props.todos || []}
filter={this.props.currentFilter}
toggleTodo={this.props.toggleTodo}
/>
<Filters setFilter={this.props.setFilter}
filter={this.props.currentFilter} />
</div>
)
}
}
Bootstrap
// app.js
import { ApolloProvider } from 'react-apollo'
let combinedReducer = combineReducers({
filter,
apollo: client.reducer(),
})
const store = compose(
applyMiddleware(client.middleware())
)(createStore)(combinedReducer)
render(
<ApolloProvider store={store} client={client}>
<TodoApp />
</ApolloProvider>,
document.getElementById('root')
)
Main APIs
- query
- mutate
- updateQueries (reducer)
query
// TodoApp.js
import { graphql } from 'react-apollo'
import gql from 'graphql-tag'
const withTodos = graphql(
gql`query todos {
allTodoes {
id complete text
}
}`, {
props: ({ ownProps, data }) => {
if (data.loading) return { userLoading: true }
if (data.error) return { hasErrors: true }
return {
todos: data.allTodoes,
}
}
})
mutate
// TodoApp.js
const withAddTodo = graphql(
gql`mutation addTodo($text: String!) {
createTodo(text: $text, complete: false) { id text complete }
}`,
{
props: ({ ownProps, mutate }) => ({
addTodo (text) {
return mutate({
variables: { text },
updateQueries: {
todos: (state, { mutationResult }) => {
return {
allTodoes: [...state.allTodoes,
mutationResult.data.createTodo
],
}
...
mutate (immutability-helper)
// TodoApp.js
const withAddTodo = graphql(
gql`mutation addTodo($text: String!) {
createTodo(text: $text, complete: false) { id text complete }
}`,
{
props: ({ ownProps, mutate }) => ({
addTodo (text) {
return mutate({
variables: { text },
updateQueries: {
todos: (state, { mutationResult }) => {
return update(state, {
allTodoes: {
$push: [ mutationResult.data.createTodo ],
},
})
...
connect
// TodoApp.js
import { connect } from 'react-redux'
const withTodos = graphql(...)
const withAddTodo = graphql(...)
const withToggleTodo = graphql(...)
const TodoAppWithState = connect(
(state) => ({ currentFilter: state.filter }),
(dispatch) => ({
setFilter: (filter) => {
dispatch({
type: 'SET_FILTER',
filter,
})
},
}),
)(TodoApp)
export default withTodos(withAddTodo(withToggleTodo(TodoAppWithState)))
Subscriptions
(Experimental)
GraphQL Server

source: blog
Dependencies
- Server side package to connect with the pub/sub system (graphql-subscriptions)
- WebSocket client + server (subscriptions-transport-ws)
Setup
// client.ts
import { Client } from 'subscriptions-transport-ws';
export const wsClient = new Client('ws://subscriptions.graph.cool/ZZZ', {
timeout: 10000
});
Posts Schema
schema {
query: Query,
mutation: Mutation,
subscription: Subscription
}
type Post {
id: ID!
description: String!
imageUrl: String!
}
type Mutation {
createPost(description: String!, imageUrl: String!): Post
}
type Subscription {
createPost(): Post
}
wsClient.subscribe
// feed.component.ts
wsClient.subscribe({
query: `subscription newPosts {
createPost { id description imageUrl }
}`,
variables: null
}, (err, res) => {
// res.createPost = { id: 34, description: 'woot', imageUrl: '...' }
// err = [{ message: 'Connection Timeout', stack: '...' }]
});
Why use GraphQL?

Some reasons
- Declarative
- De-coupled from storage
- Validated and structured
- Facilitates Collaboration
- Super fast

Examples


World Chat
Links

Thanks!

Unleashing the power of GraphQL
By Gerard Sans
Unleashing the power of GraphQL
GraphQL is awesome! After only a year it has got a lot of attention from the community. Many implementations have emerged and it’s just getting better. Is GraphQL right for you? Is it a query language or runtime? In this talk I am going to take you from 0 to hero. ;)
- 5,515