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

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

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,627