I'm using react native and aws amplify to interface with graphQL. However when making this mutation I receive the error ""Variable 'input' has coerced Null value for NonNull type '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);
}
}
Here is my schema:
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")
}
And here is the mutation I'm trying to call that AWS generated:
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
}
}
}
`;
I have tried solutions from similar questions such as changing the syntax of the mutator argument but the error persists. Any idea of how to solve this?
It isn't the student id that is the problem. It has to do with this connection:
class: Class! @connection(name: "ClassStudents")
The Class item is a GraphQL connected type. It isn't an id. You probably have a column that is something like: classStudentId or studentClassId. I am still learning exactly how this column gets auto-created in AppSync, but it is how AppSync manages the connection in DynamoDB. You have to specify that id column, not class:.
eg:
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);
}
}
As an example, I can share the problem I just worked through that led me here while I was trying to fix it:
Schema:
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")
}
Mutation:
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
}
}
}
}
`;
Normally, I could create a message like this:
const submitData = {
associationId: association.id,
content: fields.message,
}
await API.graphql(graphqlOperation(CreateMessage, { input: submitData }))
Amplify will get the current user id from Cognito (using auth) and will create a unique id for me.
However, since I specified that owner would be the connection key field, I now have to add the user's id to the owner column manually unfortunately, I can't leave it empty and rely on Amplify anymore.
I have made owner a DynamoDB requirement to connect to the User table instead of just a Cognito connection field that Amplify can use. I could specify the user id in a separate column like authorId, but since the User table uses the Cognito id anyway, I am trying to condense these into one column... So now I have to do this, or I get the same error you were getting:
const submitData = {
associationId: association.id,
content: fields.message,
owner: user.id,
}
await API.graphql(graphqlOperation(CreateMessage, { input: submitData }))
Your situation is obviously different, but you need to find out how it is actually storing the Class id and manually specify it. Or you can force it to use a key field that you want like classId, but you can't use the connection item itself. That isn't how it is stored.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With