【问题标题】:AWS graphQL error: "Variable 'input' has coerced Null value for NonNull type 'ID!'"AWS graphQL 错误:“变量 'input' 已强制 NonNull 类型 'ID!' 的 Null 值!”
【发布时间】:2019-10-24 09:25:10
【问题描述】:

我正在使用 react native 和 aws amplify 与 graphQL 交互。但是,在进行此突变时,我收到错误““变量'输入'已强制非空类型'ID!'的空值”。

addStudent = async (classData) => {
    try {
    let user = await Auth.currentAuthenticatedUser();
    const emailAttribute = user.attributes.email;
    const studentObj = {
      name: this.state.studentName,
      email: emailAttribute,
      class: classData.id,
    }
    await API.graphql(graphqlOperation(mutations.createStudent, { input: studentObj }));
} catch (err) {
    console.error(err);
}
}

这是我的架构:

type Class @model @auth(rules: [{ allow: owner, queries: null}]) {
id: ID!
name: String!
password: String!
email: String!
students: [Student] @connection(name: "ClassStudents")
}

type Student @model @auth(rules: [{ allow: owner, queries: null}]) {
id: ID!
name: String!
email: String!
class: Class! @connection(name: "ClassStudents")
attendance: [Attendance] @connection(name: "StudentAttendance")
}

这是我试图称之为 AWS 生成的突变:

export const createStudent = `mutation CreateStudent($input: CreateStudentInput!) {
  createStudent(input: $input) {
id
name
email
class {
  id
  name
  password
  email
  students {
    nextToken
  }
}
attendance {
  items {
    id
    date
  }
  nextToken
}
}
}
`;

我已经尝试过类似问题的解决方案,例如更改 mutator 参数的语法,但错误仍然存​​在。知道如何解决这个问题吗?

【问题讨论】:

  • 没有在输入对象中定义id属性(变异参数)studentObj
  • @xadm 当我调用 mutator createClass 时,我不必传入 id 值。在放大文档中,它们从不传递 id 的值。
  • 使idCreateStudentInput 中可以为空

标签: javascript amazon-web-services react-native graphql aws-sdk


【解决方案1】:

是的,我认为突变的第一行应该是这样的;

export const createStudent = `mutation CreateStudent($input: ID!)

【讨论】:

    【解决方案2】:

    问题不在于学生证。它与此连接有关:

    class: Class! @connection(name: "ClassStudents")
    

    Class 项是 GraphQL 连接类型。这不是身份证。您可能有一列类似于:classStudentIdstudentClassId。我仍在学习如何在 AppSync 中自动创建此列,但它是 AppSync 在 DynamoDB 中管理连接的方式。您必须指定该 id 列,而不是 class:

    例如:

    addStudent = async (classData) => {
      try {
        let user = await Auth.currentAuthenticatedUser();
        const emailAttribute = user.attributes.email;
        const studentObj = {
          name: this.state.studentName,
          email: emailAttribute,
          studentClassId: classData.id,
        }
        await API.graphql(graphqlOperation(mutations.createStudent, { input: studentObj }));
      } catch (err) {
        console.error(err);
      }
    }
    

    我的例子

    作为一个例子,我可以分享一下我刚刚解决的问题,这导致我在尝试修复它时来到这里:

    架构

    type Message @model
      @auth(
        rules: [
          { allow: owner, operations: [create, read, update, delete] }
          { allow: groups, groups: ["everyone"], operations: [read] }
        ]
      )
      @key(fields: ["associationId", "createdAt"]) {
      id: ID!
      associationId: String!
      content: String!
      createdAt: AWSDateTime!
      author: User! @connection(name: "UserMessages", keyField: "owner")
    }
    

    变异

    export const createMessage = /* GraphQL */ `
      mutation CreateMessage(
        $input: CreateMessageInput!
        $condition: ModelMessageConditionInput
      ) {
        createMessage(input: $input, condition: $condition) {
          id
          associationId
          content
          createdAt
          owner
          author {
            id
            firstName
            lastName
            email
            phone
            avatar {
              bucket
              region
              key
            }
          }
        }
      }
    `;
    

    通常,我可以创建这样的消息:

    const submitData = {
      associationId: association.id,
      content: fields.message,
    }
    await API.graphql(graphqlOperation(CreateMessage, { input: submitData }))
    

    Amplify 将从 Cognito 获取当前用户 ID(使用身份验证)并为我创建一个唯一 ID。

    然而,由于我指定 owner 将是连接键字段,我现在必须手动将用户的 ID 添加到所有者列中,我不能将其留空并依赖不再放大。

    我已将所有者 DynamoDB 要求设置为连接到 User 表,而不仅仅是 Amplify 可以使用的 Cognito 连接字段。我可以在像authorId 这样的单独列中指定用户ID,但是由于用户表无论如何都使用Cognito id,我试图将它们压缩成一列......所以现在我必须这样做,否则我会得到你得到同样的错误:

    const submitData = {
      associationId: association.id,
      content: fields.message,
      owner: user.id,
    }
    await API.graphql(graphqlOperation(CreateMessage, { input: submitData }))
    

    你的情况显然不同,但你需要了解它实际上是如何存储Class id 并手动指定它。或者您可以强制它使用您想要的关键字段,例如classId,但您不能使用连接项本身。这不是它的存储方式。

    【讨论】:

      猜你喜欢
      • 2018-09-11
      • 2020-05-01
      • 2019-01-30
      • 2019-05-29
      • 1970-01-01
      • 2018-01-20
      • 2019-11-02
      • 2018-10-21
      • 2021-05-19
      相关资源
      最近更新 更多