GraphQL nested mutations with Apollo: small fatigue, max gain
The Scene
I am doing some experimentation and I want to try something with GraphQL on a React project. I already know something about GraphQL but I never really used it by myself.
I begin searching for a good GraphQL backend and I settle with Graphcool which seems the best out there at this moment: has a lot of guides and tutorials, it integrates with other services, it is very flexible and it’s free for developers. Bright green lights!
Graphcool has quickstart guides for both Apollo and Relay but I already decided what to use so I begin yarn-ing what it needs on my React project:
"apollo-client": "^0.8.1",
"graphql-tag": "^1.2.3",
"react-apollo": "^0.9.0",
The Mission
I think about something not so original but always fun to work with: music bands and albums and songs and stuff.. always more exciting than Northwind Traders or Contoso Ltd. :)
So I just want to read/write data from/to Graphcool.
In GraphQL when you want to read you need Queries, when you want to write you need Mutations.
I am not writing about queries because the focus of this story is about nested mutations and because queries are well explained and I got no problems during the implementation.
LET THE PARTY BEGINS
With the Graphcool “Console” (an awesome interface for db modelling) I created a rough-and-ready structure.
type Band {
name: String!
country: String
website: String
members: [Person]
contact: Person
albums: [Album]
}type Person {
firstName: String!
lastName: String!
}type Album {
name: String!
year: Int!
songs: [Song]
}type Song {
trkNr: Int
title: String!
duration: String
}
As you can see we nested two arrays on two different levels starting from the albums field of the Band model.
So, to be clear, I want to store all this info using some data about STORMO music band, and I want to do it with a single mutation!
The Problem
The party suddenly crashes (and STORMO stop playing!) when I realize I don’t know how to create nested mutations, nor the (anyway very good) Apollo documentation can help me out.
Moreover I was brave enough to use arrays and now my eyes are lost in the window… the physical one!!
The Help
After a few not-worth-mentioning tries i decide to use the salvific Graphcool slack support where I begin stalking in the general channel.
Nilan Marktanner, from Graphcool staff begins to help me in no time and when i finally explain in a comprehensible way my situation, he hands me…
The Solution
Thanks to Nilan I relaize three things:
- the importance and, yes, the beauty, of a timely assistance
- nested mutations on Graphcool are improved and easyer to use
- when you write a nested mutation there is no need to write about the types of the nested objects!
and that was exactly what i needed.
Code Time
The mutation I have to build
mutation {
createBand(
name: "Stormo"
country: "Italy"
website: "https://stormo.bandcamp.com/"
members: [{
firstName: "Luca"
lastName: "Rocco"
}, {
firstName: "Federico"
lastName: "Trimeri"
}, {
firstName: "Giacomo"
lastName: "Rento"
}, {
firstName: "Gabriele"
lastName: "Coldepin"
}]
contact: {
firstName: "Giacomo"
lastName: "Rento"
}
albums: [{
name: "SOSPESI NEL VUOTO BRUCEREMO IN UN ATTIMO E IL CERCHIO SARÀ CHIUSO"
year: 2014
songs: [{
trkNr: 1
title: "In Volo"
duration: "02:50"
}, {
trkNr: 2
title: "Supernova"
duration: "02:10"
}, {
trkNr: 3
title: "Fuga"
duration: "01:24"
}, {
trkNr: 4
title: "Perchè La Bambina Cade"
duration: "02:46"
}]
}, {
name: "7"
year: 2009
songs: [{
trkNr: 1
title: "Incosiderata Putrefazione"
duration: "03:18"
}, {
trkNr: 2
title: "Abbandono La Mia Volontà"
duration: "03:20"
}]
}, {
name: "Self-Titled EP"
year: 2007
songs: [{
trkNr: 4
title: "Quando Non Ci Sei"
duration: "02:08"
}, {
trkNr: 5
title: "Al Punto Di Non Ritorno"
duration: "04:36"
}]
}]
) {
id
members {
id
}
contact {
id
}
albums {
id
songs {
id
}
}
}
}
Using Apollo Client, I specify input arguments with GraphQL variables, so let’s see how it looks in this case:
import gql from 'graphql-tag';const BandMutation = gql`
mutation (
$name: String!
$country: String
$website: String
$Members: [Person]
$Contact: Person
$Albums: [Albums]
) {
createBand(
name: $name
Country: $Country
Members: $Members
Contact: $Contact
Albums: $Albums
) {
id
members {
id
}
contact {
id
}
albums {
id
songs {
id
}
}
}
}
`;
Using a form I compose the data like this: (but pay attention, apollo wants this object called ‘variables’ and nothing else!)
const variables = {
name: "Stormo",
country: "Italy",
website: "https://stormo.bandcamp.com/"
members: [{
firstName: "Luca",
lastName: "Rocco",
}, {
firstName: "Federico",
lastName: "Trimeri",
}, {
firstName: "Giacomo",
lastName: "Rento",
}, {
firstName: "Gabriele",
lastName: "Coldepin",
}],
contact: {
firstName: "Giacomo",
lastName: "Rento",
},
albums: [{
name: "SOSPESI NEL VUOTO BRUCEREMO IN UN ATTIMO E IL CERCHIO SARÀ CHIUSO",
year: 2014,
songs: [{
trkNr: 1,
title: "In Volo",
duration: "02:50" ,
}, {
trkNr: 2,
title: "Supernova",
duration: "02:10" ,
}, {
trkNr: 3,
title: "Fuga",
duration: "01:24" ,
}, {
trkNr: 4,
title: "Perchè La Bambina Cade",
duration: "02:46",
}]
}, {
name: "7",
year: 2009,
songs: [{
trkNr: 1,
title: "Incosiderata Putrefazione",
duration: "03:18",
}, {
trkNr: 2,
title: "Abbandono La Mia Volontà",
duration: "03:20",
}]
}, {
name: "Self-Titled EP",
year: 2007,
songs: [{
trkNr: 4,
title: "Quando Non Ci Sei",
duration: "02:08",
}, {
trkNr: 5,
title: "Al Punto Di Non Ritorno",
duration: "04:36",
}]
}]
}
Finally, inside my React component I can use all of this to send my data to Graphcool
import React, { Component } from 'react';
import { graphql, compose } from 'react-apollo';
import BandMutation from './../graphql/BandMutation';class CompanySettings extends Component {
constructor(props) {
super(props);
this.sendData = this.sendData.bind(this);
}sendData(variables) {
this.props.CreateBand({ variables })
.then((response) => {
window.alert('You submitted data about a new band');
}).catch((e) => {
console.error(e);
});
}render() {
return <FormCreateBand onSubmit={this.sendData} />;
}
}export default compose(
// with this I can use the mutation with this.props.CreateBand
graphql(BandMutation, { name: 'CreateBand' }),
// I can write here other mutations or queries
)(CompanySettings);
Conclus… But wait! This is the beginning actually
- GraphQL is not the future, is the present, and it’s soo disarmingly good, in loving memory of REST
- Graphcool is an awesome service and its staff is careful and hyperactive (i’m quite sure they don’t sleep neither)
- Was there some fatigue?… Yes, of course! But with this kind of fatigue, for every minute of time that you invest, you will save A LOT more later, it depends on the project.
P.S. The party now is going crazy, thanks to Storm{O}!!
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising &sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!