Migrate react-apollo from v2 to v3 in conjunction with AWS AppSync
Tags: apollo, react, aws, appsync
Published: 2020-03-26 14:28:17

The implementation between [Apollo](https://www.apollographql.com/) and [AWS AppSync](https://aws.amazon.com/appsync/) is very good, but some time ago version 3 of [react-apollo](https://github.com/apollographql/react-apollo) was released. Unfortunately this version is no longer compatible with the [aws-appsync](https://github.com/awslabs/aws-mobile-appsync-sdk-js) package.

The latest version of react-apollo provides new [React Hooks](https://reactjs.org/docs/hooks-intro.html) and introduces a new monorepo structure.

You'll find an issue on [GitHub](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/448) that describes the incompatibility:

{% github https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/448 %}

I didn't follow up on it anymore, because I thought there would be an update to fix the problem soon. But that's not what happened 🙃. The issue now contains 51 comments. Between all the comments with the question about "the current status" is hidden the [solution](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/448#issuecomment-541229659).

## Implementation with react-apollo version `2.x`

In this example I use the [aws-appsync](https://www.npmjs.com/package/aws-appsync), [aws-appsync-react](https://www.npmjs.com/package/aws-appsync-react) and [react-apollo](https://www.npmjs.com/package/react-apollo) package. Your implementation should probably look like the following:

```js
import React from 'react'
import ReactDOM from 'react-dom'
import Auth from '@aws-amplify/auth'
import AWSAppSyncClient from 'aws-appsync'
import { ApolloProvider } from 'react-apollo'
import { Rehydrated } from 'aws-appsync-react'

import App from './containers/App'
import AppSyncConfig from './aws-exports'

const appSyncConfig = {
  url: AppSyncConfig.graphqlEndpoint,
  region: AppSyncConfig.region,
  auth: {
    type: AppSyncConfig.authenticationType,
    jwtToken: async () => (await Auth.currentSession()).getIdToken().getJwtToken()
  },
  disableOffline: true
}

const appSyncOptions = {
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network'
    }
  }
}

const client = new AWSAppSyncClient(appSyncConfig, appSyncOptions)

ReactDOM.render(
  <ApolloProvider client={client}>
    <Rehydrated>
      <App />
    </Rehydrated>
  </ApolloProvider>,
  document.getElementById('app')
)
```

## Implementation with react-apollo version `3.x`:

⚠️ This solution does not include offline support. ⚠️

With the latest version of react-apollo (`3.x`), the implementation also changes. For the new implementation you need the [aws-appsync-auth-link](https://www.npmjs.com/package/aws-appsync-auth-link), [aws-appsync-subscription-link](https://www.npmjs.com/package/aws-appsync-subscription-link), [apollo-link](https://www.npmjs.com/package/apollo-link), [apollo-client](https://www.npmjs.com/package/apollo-client), [apollo-cache-inmemory](https://www.npmjs.com/package/apollo-cache-inmemory) and [@apollo/react-common](https://www.npmjs.com/package/@apollo/react-common) package.

```js
import React from 'react'
import ReactDOM from 'react-dom'
import { createAuthLink } from 'aws-appsync-auth-link'
import { createSubscriptionHandshakeLink } from 'aws-appsync-subscription-link'
import { ApolloProvider } from '@apollo/react-common'
import { ApolloLink } from 'apollo-link'
import ApolloClient from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import Auth from '@aws-amplify/auth'

import App from './containers/App'
import AppSyncConfig from './aws-exports'

const config = {
  url: AppSyncConfig.graphqlEndpoint,
  region: AppSyncConfig.region,
  auth: {
    type: AppSyncConfig.authenticationType,
    jwtToken: async () => (await Auth.currentSession()).getIdToken().getJwtToken()
  }
}

const client = new ApolloClient({
  link: ApolloLink.from([
    createAuthLink(config),
    createSubscriptionHandshakeLink(config)
  ]),
  cache: new InMemoryCache(),
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network'
    }
  }
})

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('app')
)
```

## Ready for react-apollo `3.x`

Now you can use the latest features of Apollo. 🦦