Going Offline-First with GraphQL

Kadi Kraman

Offline in an

"always online" world...

A note about tooling

React Native

Apollo 2

I will be using...

{
  query posts {
    posts {
      id
      createdAt
      text
    }
  }
}
{
  mutation createPost($text: String!) {
    createPost(text: $text) {
      id
      text
      createdAt
    }
  }
}
{
  mutation deletePost($id: ID!) {
    deletePost(id: $id) {
      id
    }
  }
}

Now let's make this work

OFFLINE

Online 😊

Offline 😭

How?

Cache and persist the data and read from cache when offline

Apollo Cache Persist

https://github.com/apollographql/apollo-cache-persist

import { AsyncStorage } from 'react-native';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { persistCache } from 'apollo-cache-persist';

const cache = new InMemoryCache({...});

await persistCache({
  cache,
  storage: AsyncStorage,
});

// Continue setting up Apollo as usual.

const client = new ApolloClient({
  cache,
  ...
});

NB! Ensure persistCache resolves before loading your app!

Online 😊

Offline 😍

fetchPolicy: 'cache-first'

{
  mutation createPost($text: String!) {
    createPost(text: $text) {
      id
      text
      createdAt
    }
  }
}

What happens when we create a new post?

OPTION 1: by refetching the posts list after the mutation

How?

It gets added to the posts list on the main screen

OPTION 2: optimistic update

Figure out what you THINK the resulting data will look like

export const getOptimisticResponse = (text: string) => ({
  __typename: 'Mutation',
  createPost: {
    __typename: 'Post',
    id: String(new Date().getTime()),
    text,
    createdAt: new Date()
  }
});

Add the "optimistic" response to your cache

import gql from 'graphql-tag';

const GET_POSTS = gql`
  query posts {
    posts {
      id
      createdAt
      text
    }
  }
`;


export const createPostUpdate = (cache, response) => {
  const cachedPosts = cache.readQuery({
    query: GET_POSTS
  });

  cache.writeQuery({
    query: GET_POSTS,
    data: {
      posts: [response.data.createPost, ...cachedPosts.posts]
    }
  });
};

Put it all together

Success?

We still need to handle the network request failed

Apollo Link Retry

https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-retry

Success!

We're online even when we're really offline

Main takeaways

To make your app work offline:

1. Cache and persist your data

2. Always write optimistic updates for mutations

3. Retry applicable mutations

Do this as you go and you're essentially offline first!

https://github.com/kadikraman/offline-first-mobile-example

My sample app from the screenshots:

Thank you!

https://slides.com/kadikraman/offline-first/fullscreen

These slides:

Going Offline-First with GraphQL

By Kadi Kraman

Going Offline-First with GraphQL

GraphQL Finland 2018

  • 231
Loading comments...

More from Kadi Kraman