【问题标题】:Graphql apollo client returning null value from AppSyncGraphql apollo 客户端从 AppSync 返回空值
【发布时间】:2019-01-04 00:54:22
【问题描述】:

我有一个 AppSync api 设置,具有特定的突变设置。当我在 AppSync 中测试该突变时,效果很好。但是,当我尝试在反应应用程序中使用相同的查询时,我得到一个空值。但是,当我在浏览器中查看网络选项卡时,AppSync 正在返回正确的数据。

我的 React 应用中有以下突变:

import gql from 'graphql-tag';

export default gql`
mutation CreateUser(
  $email: String!,
  $name: String
) {
  createUser(input: {
    email: $email
    name: $name
  }) {
    __typename
    id
  }
}
`;

我的 React 组件(为简洁起见略有删节):

import React, { Component } from 'react';
import MutationCreateUser from '../GraphQL/MutationCreateUser';
import { graphql } from "react-apollo";

class UserForm extends Component {

  state = {
    name: '',
    email: '',
    ... 
    err: null
  }

  ...

  submit = async () => {
    const { createUser, history } = this.props;
    const user = this.state;
    try {
      const result = await createUser({
        name: user.name,
        email: user.email
      });
      // This shows { "data": { "createUser": "null" } }
      console.log('RES', result);
    } catch (e) {
      this.setState({ err: e.message });
    }
    ... 
  }
  ... 
}

export default graphql(
  MutationCreateUser,
  {
    props: ({ mutate }) => {
      return {
        createUser: (user) => {          
          return mutate({
            variables: user
          });
        }
      }
    }
  }
)(UserForm);

当我在网络选项卡中检查查询时,我看到: {"data":{"createUser":{"__typename":"User","id":"860b7cec-e882-4242-aca0-d4865154b640"}}}

但是,在我的 React 组件中,我看到: { "data": { "createUser": "null" } }

我不确定我是否遗漏了有关如何使用 Apollo 设置组件的内容,这意味着数据未正确加载。但查询本身似乎工作正常。

数据也按预期正确存储在 DynamoDB 中。

这是我的请求映射:

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
  },
  "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
  "condition": {
    "expression": "attribute_not_exists(#id)",
    "expressionNames": {
      "#id": "id",
    },
  },
}

我的响应映射:

$util.toJson($ctx.result)

最后是我的架构:

input CreateQuestionInput {
    text: String!
    sectionId: ID!
}

input CreateScoreInput {
    score: Int!
    questionId: ID!
    userId: ID!
}

input CreateSectionInput {
    title: String
    subSection: String
}

input CreateUserInput {
    email: String!
    name: String
    jobTitle: String
    jobTitleShare: Boolean
    department: String
    level: Int
    yearRange: Int
    industry: String
    orgSize: Int
}

input DeleteQuestionInput {
    id: ID!
}

input DeleteScoreInput {
    id: ID!
}

input DeleteSectionInput {
    id: ID!
}

input DeleteUserInput {
    id: ID!
}

type Mutation {
    createSection(input: CreateSectionInput!): Section
    updateSection(input: UpdateSectionInput!): Section
    deleteSection(input: DeleteSectionInput!): Section
    createScore(input: CreateScoreInput!): Score
    updateScore(input: UpdateScoreInput!): Score
    deleteScore(input: DeleteScoreInput!): Score
    createQuestion(input: CreateQuestionInput!): Question
    updateQuestion(input: UpdateQuestionInput!): Question
    deleteQuestion(input: DeleteQuestionInput!): Question
    batchCreateQuestion(questions: [CreateQuestionInput]!): [Question]
    createUser(input: CreateUserInput!): User
    updateUser(input: UpdateUserInput!): User
    deleteUser(input: DeleteUserInput!): User
}

type Query {
    getSection(id: ID!): Section
    listSections(filter: TableSectionFilterInput, limit: Int, nextToken: String): SectionConnection
    getScore(id: ID!): Score
    listScores(filter: TableScoreFilterInput, limit: Int, nextToken: String): ScoreConnection
    getQuestion(id: ID!): Question
    listQuestions(filter: TableQuestionFilterInput, limit: Int, nextToken: String): QuestionConnection
    getUser(id: ID!): User
    listUsers(filter: TableUserFilterInput, limit: Int, nextToken: String): UserConnection
}

type Question {
    id: ID!
    text: String!
    sectionId: ID!
}

type QuestionConnection {
    items: [Question]
    nextToken: String
}

type Schema {
    query: Query
}

type Score {
    id: ID!
    score: Int!
    questionId: ID!
    userId: ID!
}

type ScoreConnection {
    items: [Score]
    nextToken: String
}

type Section {
    id: ID!
    title: String
    subSection: String
    questions: [Question]
}

type SectionConnection {
    items: [Section]
    nextToken: String
}

type Subscription {
    onCreateSection(id: ID, title: String): Section
        @aws_subscribe(mutations: ["createSection"])
    onUpdateSection(id: ID, title: String): Section
        @aws_subscribe(mutations: ["updateSection"])
    onDeleteSection(id: ID, title: String): Section
        @aws_subscribe(mutations: ["deleteSection"])
    onCreateScore(
        id: ID,
        score: Int,
        questionId: ID,
        userId: ID
    ): Score
        @aws_subscribe(mutations: ["createScore"])
    onUpdateScore(
        id: ID,
        score: Int,
        questionId: ID,
        userId: ID
    ): Score
        @aws_subscribe(mutations: ["updateScore"])
    onDeleteScore(
        id: ID,
        score: Int,
        questionId: ID,
        userId: ID
    ): Score
        @aws_subscribe(mutations: ["deleteScore"])
    onCreateQuestion(id: ID, text: String, sectionId: ID): Question
        @aws_subscribe(mutations: ["createQuestion"])
    onUpdateQuestion(id: ID, text: String, sectionId: ID): Question
        @aws_subscribe(mutations: ["updateQuestion"])
    onDeleteQuestion(id: ID, text: String, sectionId: ID): Question
        @aws_subscribe(mutations: ["deleteQuestion"])
    onCreateUser(
        id: ID,
        email: String,
        jobTitle: String,
        jobTitleShare: Boolean,
        department: String
    ): User
        @aws_subscribe(mutations: ["createUser"])
    onUpdateUser(
        id: ID,
        email: String,
        jobTitle: String,
        jobTitleShare: Boolean,
        department: String
    ): User
        @aws_subscribe(mutations: ["updateUser"])
    onDeleteUser(
        id: ID,
        email: String,
        jobTitle: String,
        jobTitleShare: Boolean,
        department: String
    ): User
        @aws_subscribe(mutations: ["deleteUser"])
}

input TableBooleanFilterInput {
    ne: Boolean
    eq: Boolean
}

input TableFloatFilterInput {
    ne: Float
    eq: Float
    le: Float
    lt: Float
    ge: Float
    gt: Float
    contains: Float
    notContains: Float
    between: [Float]
}

input TableIDFilterInput {
    ne: ID
    eq: ID
    le: ID
    lt: ID
    ge: ID
    gt: ID
    contains: ID
    notContains: ID
    between: [ID]
    beginsWith: ID
}

input TableIntFilterInput {
    ne: Int
    eq: Int
    le: Int
    lt: Int
    ge: Int
    gt: Int
    contains: Int
    notContains: Int
    between: [Int]
}

input TableQuestionFilterInput {
    id: TableIDFilterInput
    text: TableStringFilterInput
    sectionId: TableIDFilterInput
}

input TableScoreFilterInput {
    id: TableIDFilterInput
    score: TableIntFilterInput
    questionId: TableIDFilterInput
    userId: TableIDFilterInput
}

input TableSectionFilterInput {
    id: TableIDFilterInput
    title: TableStringFilterInput
}

input TableStringFilterInput {
    ne: String
    eq: String
    le: String
    lt: String
    ge: String
    gt: String
    contains: String
    notContains: String
    between: [String]
    beginsWith: String
}

input TableUserFilterInput {
    id: TableIDFilterInput
    email: TableStringFilterInput
    jobTitle: TableStringFilterInput
    jobTitleShare: TableBooleanFilterInput
    department: TableStringFilterInput
    level: TableIntFilterInput
    yearRange: TableIntFilterInput
    industry: TableStringFilterInput
    orgSize: TableIntFilterInput
}

input UpdateQuestionInput {
    id: ID!
    text: String
    sectionId: ID
}

input UpdateScoreInput {
    id: ID!
    score: Int
    questionId: ID
    userId: ID
}

input UpdateSectionInput {
    id: ID!
    title: String
}

input UpdateUserInput {
    id: ID!
    email: String
    jobTitle: String
    jobTitleShare: Boolean
    department: String
    level: Int
    yearRange: Int
    industry: String
    orgSize: Int
}

type User {
    id: ID!
    email: String
    jobTitle: String
    jobTitleShare: Boolean
    department: String
    level: Int
    yearRange: Int
    industry: String
    orgSize: Int
}

type UserConnection {
    items: [User]
    nextToken: String
}

请求在 AppSync 中有效:

【问题讨论】:

    标签: reactjs amazon-web-services graphql aws-appsync


    【解决方案1】:

    由于数据已正确存储在 DynamoDB 中,看起来响应映射模板中可能存在类型不匹配。请使用 ALL 作为设置为您的 API 启用 Cloudwatch 日志记录。然后,您可以检查 CloudWatch 日志以获取评估的响应映射模板,然后将 ctx.result.data 与用户类型的形状进行比较。

    如果仍然无法正常工作,请在此处发布您的架构和映射模板,以便我可以尝试复制它。谢谢。

    【讨论】:

    • 谢谢。由于完全相同的查询/映射模板在 AppSync 控制台中工作,我怀疑客户端正在发生其他事情。您能否为您的 API 启用 CloudWatch logs ALL 设置,然后尝试从 ReactJS 客户端运行此查询。完成此操作后,从响应标头中获取 requestId,并查看 CloudWatch 日志。请从日志中发布生成的 ResponseMapping 模板,以便我们检查响应映射中上下文的形状。
    • 你找到解释了吗?我正在一个 Angular 应用程序中试验同样的事情。
    猜你喜欢
    • 2018-08-26
    • 2020-05-15
    • 2019-06-22
    • 2022-12-12
    • 2018-10-23
    • 2021-09-23
    • 1970-01-01
    • 2016-08-31
    • 2020-09-19
    相关资源
    最近更新 更多