slides.com/gerardsans | @gerardsans
GraphQL created at Facebook
Support Mobile Native Teams
GitHub announces GraphQL API
New GraphQL website
First GraphQL Summit
GraphQL First
GraphQL Europe
Apollo Client 0.10.0 (RC-0)
// GET '/graphql'
{
user(name: "gsans") {
twitter
}
}
// result
{
"user": {
"twitter": "@gerardsans"
}
}
source: blog
<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>
schema {
query: Query,
mutation: Mutation
}
type Query {
allTodoes(skip: Int, take: Int): [Todo!]!
}
type Todo {
id: ID!
text: String!
complete: Boolean!
}
schema {
query: Query,
mutation: Mutation
}
type Mutation {
createTodo(text: String!, complete: Boolean!): Todo
updateTodo(id: ID!, text: String, complete: Boolean): Todo
}
source: blog
// 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 })
// 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>
)
}
}
// 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')
)
// 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,
}
}
})
// 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
],
}
...
// 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 ],
},
})
...
// 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)))
(Experimental)
source: blog
// client.ts
import { Client } from 'subscriptions-transport-ws';
export const wsClient = new Client('ws://subscriptions.graph.cool/ZZZ', {
timeout: 10000
});
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
}
// 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: '...' }]
});