DEV Community

Daniel Bayerlein
Daniel Bayerlein

Posted on • Updated on

Migrate react-apollo from v2 to v3 in conjunction with AWS AppSync

The implementation between Apollo and AWS AppSync is very good, but some time ago version 3 of react-apollo was released. Unfortunately this version is no longer compatible with the aws-appsync package.

The latest version of react-apollo provides new React Hooks and introduces a new monorepo structure.

You'll find an issue on GitHub that describes the incompatibility:

React-apollo 3.0 with aws-appsync-react #448

Xocix avatar
Xocix posted on

Do you want to request a feature or report a bug? Bug

What is the current behavior? Installing react-apollo 3.0 makes the Rehydrated component stop working. Going back to react-apollo 2.5.8 makes it work again

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Error message recieved: The context client is marked as required in Rehydrated, but its value is undefined.

What is the expected behavior? Rehydrated should have a client to be able to rehydrate

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.

Implementation with react-apollo version 2.x

In this example I use the aws-appsync, aws-appsync-react and react-apollo package. Your implementation should probably look like the following:

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')
)
Enter fullscreen mode Exit fullscreen mode

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, aws-appsync-subscription-link, apollo-link, apollo-client, apollo-cache-inmemory and @apollo/react-common package.

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')
)
Enter fullscreen mode Exit fullscreen mode

Ready for react-apollo 3.x

Now you can use the latest features of Apollo. 🦦

Latest comments (6)

Collapse
 
muninderkaur06 profile image
Muninder Kaur

I've used the 'Implementation with react-apollo version' in my project. It is working fine in development mode. But as for production what other configurations do I have to do?

Collapse
 
danielbayerlein profile image
Daniel Bayerlein

What error are you receiving?

Collapse
 
muninderkaur06 profile image
Muninder Kaur

I am not using any production level env. variable. With this code, graphQL is not able to connect and my apk is getting stuck on the screen where query is implemeneted. It is working fine only in development.

Collapse
 
danielbayerlein profile image
Daniel Bayerlein • Edited

ℹ️ Meanwhile there is a new package from Apollo called @apollo/client.

  1. npm uninstall @apollo/react-common apollo-link apollo-client apollo-cache-inmemory
  2. npm install @apollo/client
  3. Replace the obsolete imports with the new ones:
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 { ApolloProvider, ApolloClient, ApolloLink, InMemoryCache } from '@apollo/client'
import Auth from '@aws-amplify/auth'
Enter fullscreen mode Exit fullscreen mode
Collapse
 
frivolta profile image
Filippo Rivolta • Edited

not working mate: Argument of type '{ url: string; region: string; auth: { type: string; jwtToken: () => Promise; }; }' is not assignable to parameter of type '{ url: string; region: string; auth: AuthOptions; }'...

Have a look here: github.com/awslabs/aws-mobile-apps...

Collapse
 
danielbayerlein profile image
Daniel Bayerlein

Just tested again and it works for me. Can you describe your problem a bit? Which versions do you use?