Add an array of Objects to a mutation in apollo-react
Asked Answered
M

2

9

I am using react-apollo on the front-end and graphcool on the backend. I have a mutation that creates a tutorial like so:

const CREATE_TUTORIAL_MUTATION = gql`
  mutation CreateTutorialMutation(
    $author: String
    $link: String
    $title: String!
    $postedById: ID!
    $completed: Boolean!
  ) {
    createTutorial(
      author: $author
      link: $link
      title: $title
      postedById: $postedById
      completed: $completed
    ) {
      author
      link
      title
      postedBy {
        id
        name
      }
      completed
    }
  }
`

It gets called in a submit handler like so...

this.props.createTutorialMutation({
      variables: {
        author,
        link,
        title,
        completed: false,
        postedById
      }
    })

Everything works wonderfully.

Now I want to add a set of tags to when I create a new tutorial. I created the input field and connected it so that the tags variable is an array of objects, each with a tag id and the tag text.

If I try and add the tags field to the mutation it needs a scalar type. But there is doesn't seem to be a scalar type for an array of objects.

If I pass the tag variable in as a parameter when I call the mutation how do I fill in the Scalar type field in the mutation ( on line 148 here https://github.com/joshpitzalis/path/blob/graphQL/src/components/Add.js) and in the schema?

I am new to graphQL and I understand that I might be approaching this completely the wrong way. If that is the case, how do I add an array of objects to a mutation in graphQL?

Mender answered 22/7, 2017 at 10:50 Comment(0)
L
12

You should add a new Tag type to your schema file and connect it to Tutorial with a new relation:

type Tutorial {
  author: String
  completed: Boolean
  link: String
  title: String!
  id: ID! @isUnique
  createdAt: DateTime!
  updatedAt: DateTime!
  postedBy: User @relation(name: "UsersTutorials")
  tags: [Tag!]! @relation(name: "TutorialTags")
}

type Tag {
  id: ID!
  tag: String!
  number: Int!
  tutorials: [Tutorial!]! @relation(name: "TutorialTags")
}

Then you can create a new tutorial and new tags using a nested create mutation like this:

const CREATE_TUTORIAL_MUTATION = gql`
  mutation CreateTutorialMutation(
    $author: String
    $link: String
    $title: String!
    $tags: [TutorialtagsTag!]!
    $completed: Boolean!
    $postedById: ID!
  ) {
    createTutorial(
      author: $author
      link: $link
      title: $title
      tags: $tags
      completed: $completed
      postedById: $postedById
    ) {
      author
      link
      title
      postedBy {
        id
        name
      }
      completed
      tags {
        id
        text
      }
    }
  }
`

This post gives more background about other approaches and their trade-offs: https://www.graph.cool/forum/t/how-do-i-add-an-array-of-objects-to-a-mutation-in-apollo-react/365/6?u=nilan

Lightman answered 31/7, 2017 at 10:4 Comment(1)
Hey man, could you do me a massive favor and take a look at a question I just posted. I think I need to add @relation to a post and shots schema. I am pretty fresh at Apollo, so maybe a silly question: But can can I simply differentiate my client schema from my server schema as long as they match? Coz my server has no idea what "@relation" is. And my client doesn't seem to like it when I start adding local schemas to interface with the server: even when they match #62114455Robot
L
1

What i understand by your requirement is that if you have the following code

const user = {
    name:"Rohit", 
    age:27, 
    marks: [10,15], 
    subjects:[
        {name:"maths"},
        {name:"science"}
    ]
};

const query = `mutation {
        createUser(user:${user}) {
            name
        }
}`

you must be getting something like

"mutation {
        createUser(user:[object Object]) {
            name
        }
}"

instead of the expected

"mutation {
        createUser(user:{
            name: "Rohit" ,
            age: 27 ,
            marks: [10 ,15 ] ,
            subjects: [
                {name: "maths" } ,
                {name: "science" } 
                ] 
            }) {
            name
        }
}"

If this is what you wanted to achieve, then gqlast is a nice tag function which you can use to get the expected result

Simply grab the js file from here and use it as:

const user = {
    name:"Rohit", 
    age:27, 
    marks: [10,15], 
    subjects:[
        {name:"maths"},
        {name:"science"}
    ]
};

const query = gqlast`mutation {
        createUser(user:${user}) {
            name
        }
}`

The result stored in the variable query will be :

"mutation {
        createUser(user:{
            name: "Rohit" ,
            age: 27 ,
            marks: [10 ,15 ] ,
            subjects: [
                {name: "maths" } ,
                {name: "science" } 
                ] 
            }) {
            name
        }
}"
Leclair answered 10/5, 2019 at 14:13 Comment(1)
This really worked for my case thank you very much basically one thing to add on for anyone in need of this is to use gql''YOUR GQLASTSTRING'' as this will generate the document node. Kudos!!Ettore

© 2022 - 2024 — McMap. All rights reserved.