Flying high with
Apollo Client 2 + React
slides.com/gerardsans | @gerardsans
Google Developer Expert
Google Developer Expert
International Speaker
Spoken at 64 events in 23 countries
Blogger
Blogger
Community Leader
900
1.2K
Trainer
Master of Ceremonies
Master of Ceremonies
GraphQL Timeline
2012
GraphQL created at Facebook
2013
React is released
2014
React Native is released
2015
GraphQL is open sourced
Relay Classic is open sourced
2016
New GraphQL website graphql.org
First GraphQL Summit
GitHub announces GraphQL API
2017
Relay Modern 1.0
Apollo Client 2.0
Relay vs Apollo Downloads
launchpad.graphql.com
graphql.com
Developer Tools
Todo App
GraphQL Schema
Type System
- Scalar Types: Int, Float, String, Boolean, ID
- Object Types: Todo
- Entry points: Query, Mutation, Subscription
Schema Syntax
- Optional: String, Todo
- Mandatory: String!, Todo!
- Arrays: [String], [Todo]
npm install --global graphcool graphcool init server
graphcool deploy graphcool console
graphcool-cli
Todos Schema
// project.graphcool
type Todo @model {
id: ID! @isUnique
text: String!
complete: Boolean!
}
demo
Apollo Client
2.0
Apollo
Cache
Apollo Client
Apollo
Link
Apollo Cache
Packages
- apollo-cache-inmemory
- apollo-cache-hermes
- apollo-cache-persist
InMemoryCache
- Normalised and flattened
- this.props.client.cache
- readQuery, writeQuery
- readFragment, writeFragment
Add Todo
const query = gql`query AllTodos {
allTodoes { id text complete }
}`;
const data = store.readQuery({ query });
const newTodo = {
id: createTodo.id,
text: input.value,
complete: false,
__typename: "Todo"
};
store.writeQuery({
query,
data: {
allTodoes: [...data.allTodoes, newTodo],
},
});
Apollo Link
Packages
- apollo-link
- apollo-link-http
- apollo-link-ws
- apollo-link-error
- apollo-link-batch
- apollo-link-polling
- apollo-link-retry
Packages (future)
- apollo-link-store
- apollo-link-rest
- apollo-link-offline
Apollo Link
- concat(link1, link2)
- split(expr, link1, link2)
- from([link1, link2])
Security Headers
import { ApolloLink } from 'apollo-link';
import { createHttpLink } from 'apollo-link-http';
const httpLink = new HttpLink({ uri: URI });
const authLink = new ApolloLink((operation, forward) => {
const token = localStorage.getItem('authtoken');
if (token) {
operation.setContext({
headers: { Authorization: token }
});
}
return forward(operation);
})
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});
Using GraphQL
GraphQL Server
source: blog
Dependencies
- JavaScript client for GraphQL (apollo-client)
- API to run queries and mutations (react-apollo)
- Apollo Link (apollo-link)
- Store (apollo-cache-inmemory)
- Template literal (graphql-tag)
Setup
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
export const client = new ApolloClient({
link: new HttpLink({ uri: URI}),
cache: new InMemoryCache()
});
Bootstrap
// index.js
import { ApolloProvider } from 'react-apollo';
import { client } from './client';
ReactDOM.render(
<ApolloProvider client={client}>
<App/>
</ApolloProvider>,
document.getElementById('root')
);
registerServiceWorker();
Todos Schema
schema {
query: Query,
mutation: Mutation
}
type Todo {
id: ID!
text: String!
complete: Boolean!
}
type Query {
allTodoes(skip: Int, take: Int): [Todo!]!
}
query
const TODOS = gql`
query todos {
allTodoes { id text complete }
}`
const withTodos = graphql(TODOS, {
props: ({ ownProps, data }) => {
if (data.loading) return { loading: true }
if (data.error) return { hasErrors: true }
return {
todos: data.allTodoes,
}
},
})
mutate
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 },
update: (store, { data: { createTodo } }) => {
const data = store.readQuery({ query: TODOS });
data.allTodoes.push(createTodo);
store.writeQuery({ query: TODOS, data });
},
})
},
}),
})
demo
Adding Realtime
GraphQL Server
source: blog
Dependencies
- Apollo link for Websockets
- WebSocket subscriptions
Setup
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
export const client = new ApolloClient({
link: setupLink(),
cache: new InMemoryCache()
});
Setup
function setupLink() {
const httpLink = new HttpLink({ uri: URI });
const wsLink = new WebSocketLink({
uri: URI_WS,
options: { reconnect: true }
});
const isSubscription = ({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind==='OperationDefinition' && operation==='subscription';
}
const link = split(
isSubscription,
/* if true use */ wsLink,
/* otherwise */ httpSecured,
);
return link;
}
Todos Schema
schema {
subscription: Subscription
}
type Mutation {
createTodo(text: String!, complete: Boolean!): Todo
deleteTodo(id: ID!): Todo
}
type Subscription {
Todo(filter: [CREATED, UPDATED, DELETED]): {
mutation: [CREATED, UPDATED, DELETED]
node: Todo
updatedFields: [String!]
previousValues: Todo
}
}
subscribeToMore
// app.component.ts
query.subscribeToMore({
document: gql`
subscription {
Todo(filter: { mutation_in: [CREATED] }) {
node { id complete text }
}
}
`,
updateQuery: (state, { subscriptionData }) => {
...
}
subscribeToMore
updateQuery: (state, { subscriptionData }) => {
const {node} = subscriptionData.data.Todo;
if (!state.allTodoes.find(todo => todo.id === node.id)) {
state.allTodoes.push(node);
}
return {
allTodoes: todos
}
}
demo
Why use GraphQL?
Some reasons
- Declarative
- De-coupled from storage
- Validated and structured
- Facilitates Collaboration
- Super fast
More
gsans/todo-apollo-v2-react
Flying high with Apollo Client 2.0 and React
By Gerard Sans
Flying high with Apollo Client 2.0 and React
The Apollo team just released the new version of the Apollo Client. There's already a lot of hype around the new architecture using a new modular and flexible approach. In this talk, we are going to put it to test it together with React covering inc. queries, mutations and real-time subscriptions. Buckle up!
- 2,628