GraphQL nested mutations with Apollo: small fatigue, max gain

Written by alessandro.annini | Published 2017/02/10
Tech Story Tags: graphql | apollo | react | reactjs | javascript

TLDRvia the TL;DR App

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: Stringwebsite: Stringmembers: [Person]contact: Personalbums: [Album]}

type Person {firstName: String!lastName: String!}

type Album {name: String!year: Int!songs: [Song]}

type Song {trkNr: Inttitle: 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:

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: 2014songs: [{trkNr: 1title: "In Volo"duration: "02:50"}, {trkNr: 2title: "Supernova"duration: "02:10"}, {trkNr: 3title: "Fuga"duration: "01:24"}, {trkNr: 4title: "Perchè La Bambina Cade"duration: "02:46"}]}, {name: "7"year: 2009songs: [{trkNr: 1title: "Incosiderata Putrefazione"duration: "03:18"}, {trkNr: 2title: "Abbandono La Mia Volontà"duration: "03:20"}]}, {name: "Self-Titled EP"year: 2007songs: [{trkNr: 4title: "Quando Non Ci Sei"duration: "02:08"}, {trkNr: 5title: "Al Punto Di Non Ritorno"duration: "04:36"}]}]) {idmembers {id}contact {id}albums {idsongs {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: $nameCountry: $CountryMembers: $MembersContact: $ContactAlbums: $Albums) {idmembers {id}contact {id}albums {idsongs {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.CreateBandgraphql(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!


Published by HackerNoon on 2017/02/10