1
votes

I'm developing an offline-first Expo/React Native app, using GraphQL + Apollo Client + Join Monster, and storing data in a sqlite db client-side.

My schema (and the rest of the code) looks very similar to this one https://github.com/tslater/reactnative-relay-offline/blob/master/graphql/relay-schema/index.js except instead of using Relay, I am using Apollo Client as my GraphQL client.

I have a custom networkInterface that looks like:

import schema from './graphql/relay-schema'

class LocalNetworkInterface implements NetworkInterface {
  constructor(schema) {
    this.schema = schema
  }
  query(request) {
    const { query, variables } = request
    return graphql(
      this.schema,
      printAST(query),
      null,
      null,
      variables,
    )
  }
  getSchema() {
    return this.schema
  }
}

export function createLocalNetworkInterface(options) {
  const { schema } = options
  return new LocalNetworkInterface(schema)
}

const networkInterface = createLocalNetworkInterface({ schema })
const client = new ApolloClient({networkInterface})

and this works well for offline queries.

However, I'm unsure of how to adapt this in order to be able to make queries against a real server when the app detects it has an internet connection. The gql query I would issue against the server is slightly different that the one I issue against the local db, if that matters. Is https://github.com/apollographql/apollo-link something that would be helpful here?

1

1 Answers

1
votes

I found some excellent documentation from Apollo Data that deals exactly with this issue, http://dev.apollodata.com/core/network.html#CustomNetworkInterfaceExample

I combined this with the react-native-offline package to get me an isConnected prop, which I can pass alongside my query variables, and created a new HybridNetworkInterface:

import {createNetworkInterface} from 'apollo-client'
import {createLocalNetworkInterface} from './LocalNetworkInterface'

export class HybridNetworkInterface {
  constructor(opts) {
    this.localInterface = createLocalNetworkInterface(opts)
    this.networkInterface = createNetworkInterface(opts) // createNetworkInterface
  }
  query(request) {
    if (request.variables && request.variables.isConnected) {
      return this.networkInterface.query(request)
    }
    return this.localInterface.query(request)
  }
  use(middlewares) {
    this.networkInterface.use(middlewares)
    this.localInterface.use(middlewares)
    return this
  }
  useAfter(afterwares) {
    this.networkInterface.useAfter(afterwares)
    this.localInterface.useAfter(afterwares)
    return this
  }
}

export function createHybridNetworkInterface(opts) {
  return new HybridNetworkInterface(opts)
}