How to use Apollo Client with AppSync?
Asked Answered
C

2

12

AppSync uses MQTT over WebSockets for its subscription, yet Apollo uses WebSockets. Neither Subscription component or subscribeForMore in Query component works for me when using apollo with AppSync.

One AppSync feature that generated a lot of buzz is its emphasis on real-time data. Under the hood, AppSync’s real-time feature is powered by GraphQL subscriptions. While Apollo bases its subscriptions on WebSockets via subscriptions-transport-ws, subscriptions in GraphQL are actually flexible enough for you to base them on another messaging technology. Instead of WebSockets, AppSync’s subscriptions use MQTT as the transport layer.

Is there any way to make use of AppSync while still using Apollo?

Combe answered 24/10, 2018 at 3:33 Comment(0)
C
14

Ok, here is how it worked for me. You'll need to use aws-appsync SDK (https://github.com/awslabs/aws-mobile-appsync-sdk-js) to use Apollo with AppSync. Didn't have to make any other change to make subscription work with AppSync.

Configure ApolloProvider and client:

    // App.js
    import React from 'react';
    import { Platform, StatusBar, StyleSheet, View } from 'react-native';
    import { AppLoading, Asset, Font, Icon } from 'expo';
    import AWSAppSyncClient from 'aws-appsync' // <--------- use this instead of Apollo Client
    import {ApolloProvider} from 'react-apollo' 
    import { Rehydrated } from 'aws-appsync-react' // <--------- Rehydrated is required to work with Apollo

    import config from './aws-exports'
    import { SERVER_ENDPOINT, CHAIN_ID } from 'react-native-dotenv'
    import AppNavigator from './navigation/AppNavigator';

    const client = new AWSAppSyncClient({
      url: config.aws_appsync_graphqlEndpoint,
      region: config.aws_appsync_region,
      auth: {
        type: config.aws_appsync_authenticationType,
        apiKey: config.aws_appsync_apiKey,
        // jwtToken: async () => token, // Required when you use Cognito UserPools OR OpenID Connect. token object is obtained previously
      }
    })


    export default class App extends React.Component {
      render() {
        return <ApolloProvider client={client}>
          <Rehydrated>
            <View style={styles.container}>
              <AppNavigator />
            </View>
          </Rehydrated>  
        </ApolloProvider>
    }

Here is how the subscription in a component looks like:

    <Subscription subscription={gql(onCreateBlog)}>
      {({data, loading})=>{
        return <Text>New Item: {JSON.stringify(data)}</Text>
      }}
    </Subscription>
Combe answered 24/10, 2018 at 3:33 Comment(5)
I just wanted to mention that the aws-exports file comes from the main page of AppSync from the JavaScript tabs. Down in the page, there's a button that says "Download config". That's the file you want to include.Hype
In addition, if you're using TypeScript, check this link out: github.com/awslabs/aws-mobile-appsync-sdk-js/issues/362 There seems to be a Typings issue from the AppSync Client (outdated typings)Hype
@Combe Did you have any problems with broken websockets after network change? Should it re-connect automatically after e.g. VPN connect?Longrange
With this code, isn't it only working on development machine? How do you get it to work in production?Tavie
As per Jan 1, 2022 MTQQ is no longer available as protocol in AppSync docs.aws.amazon.com/appsync/latest/devguide/…Hospitium
C
4

Just to add a note about the authentication as it took me a while to work this out:

If the authenticationType is "API_KEY" then you have to pass the apiKey as shown in @C.Lee's answer.

  auth: {
    type: config.aws_appsync_authenticationType,
    apiKey: config.aws_appsync_apiKey,
  }

If the authenticationType is "AMAZON_COGNITO_USER_POOLS" then you need the jwkToken, and if you're using Amplify you can do this as

  auth: {
    type: config.aws_appsync_authenticationType,
    jwtToken: async () => {
      const session = await Auth.currentSession();
      return session.getIdToken().getJwtToken();
    }
  }

But if your authenticationType is "AWS_IAM" then you need the following:

  auth: {
    type: AUTH_TYPE.AWS_IAM,
    credentials: () => Auth.currentCredentials()
  }
Condyloma answered 7/3, 2019 at 15:10 Comment(2)
Hey Denis, Do you have a solution for AMAZON_COGNITO_USER_POOLS where Amplify is not being used? I cannot find it anywhere, but cant use Amplify on this projectLatoria
Sorry @JoshuaJames, I don't. We've used Amplify in our React Native app and in the web version we've used the Cognito UI provided by AWS. It's a bit basic but it does the job.Condyloma

© 2022 - 2024 — McMap. All rights reserved.