设置 AWSAppSyncClient、Apollo 和 React 的正确方法

Posted

技术标签:

【中文标题】设置 AWSAppSyncClient、Apollo 和 React 的正确方法【英文标题】:Proper way to setup AWSAppSyncClient, Apollo & React 【发布时间】:2020-07-03 08:58:25 【问题描述】:

我在开始使用 React、Apollo 和 AWS-AppSync 时遇到了问题。我无法解决此错误消息:

TypeError: this.currentObservable.query.getCurrentResult is not a function

我正在使用 @apollo/react-hooks 和 aws-appsync 的更新包。

我当前的设置如下所示。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

import config from './aws-exports';
import AWSAppSyncClient from 'aws-appsync';
import  ApolloProvider  from '@apollo/react-hooks';

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
    
);

ReactDOM.render(
    <ApolloProvider client=client>
        <React.StrictMode>
            <App />
        </React.StrictMode>
    </ApolloProvider>,
    document.getElementById('root')
);

我有一个函数可以进行如下查询:

import React from 'react';
import  useQuery  from '@apollo/react-hooks';
import gql from 'graphql-tag';

const Flavors = () => 

    const GET_FLAVORS = gql`
        query listAll 
            items 
                name,
                image
            
        
    `;

    const  loading, error, data  = useQuery(GET_FLAVORS);

    if(loading) return <p>loading...</p>
    if(error) return <p>Something went wrong...</p>

    return (
        <div>
        
            data.listIceCreamTypes.items.map(type => 
                return <div key=type.name>
                    <img src=type.image alt=type.name />
                    <h1>type.name</h1>
                </div>
            )
        
        </div>
    )


export default Flavors;

我经历了https://github.com/apollographql/react-apollo/issues/3148 中描述的各种解决方案,例如添加:

"resolutions": 
    "apollo-client": "2.6.3"
 

到 package.json。然后重新运行 npm install 并重新启动服务器。

似乎没有什么能解决我的问题。

编辑**这里是重现问题的回购:https://github.com/Rynebenson/IceCreamQL

【问题讨论】:

【参考方案1】:

我已经在 *** 上回答了其他相关问题。

正如其他答案中提到的,问题是因为 aws-appsync 依赖于以前版本的 apollo-client。使用分辨率不是解决此问题的“更干净”的方法,因为您正在修复与此库不完全兼容的依赖版本。

我强烈建议您以这种方式为 AWS AppSync 创建自定义 apollo 客户端:

import  ApolloProvider  from '@apollo/react-hooks';
import  ApolloLink  from 'apollo-link';
import  createAuthLink  from 'aws-appsync-auth-link';
import  createHttpLink  from 'apollo-link-http';
import  AppSyncConfig  from './aws-exports';
import ApolloClient from 'apollo-client';

const url = AppSyncConfig.graphqlEndpoint;
const region = AppSyncConfig.region;
const auth = 
  type: AppSyncConfig.authenticationType,
  apiKey: AppSyncConfig.apiKey
;
const link = ApolloLink.from([
   createAuthLink( url, region, auth ), 
   createHttpLink( uri: url )
]);
const client = new ApolloClient(
  link,
  cache: new InMemoryCache()
);

const WithProvider = () => (
  <ApolloProvider client=client>
    <App />
  </ApolloProvider>
)

export default WithProvider

我还在medium上创建了一个更详细的帖子

【讨论】:

【参考方案2】:

想发布我最近的经历。接受的答案仍然是正确的。 aws-appsync 使用与最新版本的 apollo 客户端冲突的过时软件包。

import React from 'react';
import PropTypes from 'prop-types';

// Apollo Settings
import  ApolloClient, ApolloProvider, InMemoryCache  from '@apollo/client';
import  ApolloLink  from 'apollo-link';

// AppSync
import  Auth  from 'aws-amplify';
import  createAuthLink  from 'aws-appsync-auth-link';
import  createHttpLink  from 'apollo-link-http';
import awsconfig from 'assets/lib/aws-exports';

// jwtToken is used for AWS Cognito.
const client = new ApolloClient(
  link: ApolloLink.from([
    createAuthLink(
      url: awsconfig.aws_appsync_graphqlEndpoint,
      region: awsconfig.aws_appsync_region,
      auth: 
        type: awsconfig.aws_appsync_authenticationType,
        apiKey: awsconfig.aws_appsync_apiKey,
        jwtToken: async () => (await Auth.currentSession()).getAccessToken().getJwtToken(),
      ,
    ),
    createHttpLink( uri: awsconfig.aws_appsync_graphqlEndpoint ),
  ]),
  cache: new InMemoryCache(),
);

const withApollo = ( children) => 
  return <ApolloProvider client=client><App /></ApolloProvider>;
;

withApollo.propTypes = 
  children: PropTypes.object,
  authData: PropTypes.object,
;

export default withApollo;

包.json

"@apollo/client": "^3.3.15",
"@apollo/react-hooks": "^4.0.0",
"apollo-link": "^1.2.14",
"apollo-link-http": "^1.5.17",
"aws-amplify": "^3.3.27",
"aws-amplify-react-native": "^4.3.2",
"aws-appsync-auth-link": "^3.0.4",

【讨论】:

【参考方案3】:

你必须像下面的方法一样初始化appsync。

const graphqlClient = new appsync.AWSAppSyncClient(
url: graphqlEndpoint,
region: process.env.AWS_REGION,
auth: 
    type: 'AWS_IAM',
    credentials: 
        accessKeyId: process.env.AWS_ACCESS_KEY_ID,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
        sessionToken: process.env.AWS_SESSION_TOKEN
    
,
disableOffline: true

);

【讨论】:

以上是关于设置 AWSAppSyncClient、Apollo 和 React 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

AWSAppSyncClient 未检测到 graphql 查询

设置 apollo-client 标头时出现 NetworkError

AWS AppSync 初始批量放置不更新缓存

AWSAppSync GraphQL突变执行两次

vue-apollo awsappsync - 刷新凭证

使用 multiMatch 示例的 appsync 放大过滤器