This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

Use Relay’s Input Object Mutations

4:59 JavaScript lesson by

In order to support mutations in Relay, there is a requirement that the GraphQL Server exposes mutation fields in a standardized way. This standard includes a way for mutations to accept and emit an identifier string, allowing Relay to track mutations and responses. In this video, we’ll learn how to use a helper available to us through graphql-relay to create Mutation fields that accept clientMutationId’s.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

In order to support mutations in Relay, there is a requirement that the GraphQL Server exposes mutation fields in a standardized way. This standard includes a way for mutations to accept and emit an identifier string, allowing Relay to track mutations and responses. In this video, we’ll learn how to use a helper available to us through graphql-relay to create Mutation fields that accept clientMutationId’s.

Avatar
Austin Witherow

Just finished this course. Thank you very much for the overview of GraphQL and Relay :)

A few things that I am wondering now that I am done...

1) What sort of "folder structure" is effective for GraphQL/Relay architecture?
2) Can I simply start using graphql-relay to begin rendering my data into a React/RN application?
3) Is there a recommended method to test my relay architecture? It seems like the foundation of using schemas really does this to begin with, but you know how engineers like to make sure there are no possible leaks :)

Avatar
Josh Black

Hi Austin! So glad to hear that you finished! I hope it was useful.

To answer some of your questions:

What sort of "folder structure" is effective for GraphQL/Relay architecture?

The best part of this is that your folder structure can vary depending on your needs, and if you're adding to an existing Node.js-based server, or starting from fresh. The pattern that I typically use is as follows:

src
├── index.js
├── loaders
│   ├── company.js
│   ├── employees.js
│   ├── index.js
└── schema
    ├── index.js
    ├── middleware
    │   ├── compose.js
    │   ├── index.js
    │   ├── logger.js
    │   ├── profile.js
    │   └── utilities
    │       └── trace.js
    ├── types
    │   ├── company.js
    │   ├── competitors.js
    │   ├── employee.js
    │   ├── node.js

Where schema holds all the information for the GraphQL Schema, including types, mutations, subscriptions, fields, etc. If you're interested in monitoring/profiling your resolve statements, it's also helpful to implement some form of middleware pattern on your resolve statements, for actions like logging, profiling, permissions checking, etc.

In addition, I leverage a project called DataLoader from Facebook for defining how to actually resolve each field. Typically, I locate all of the loaders that I've defined then in their own folder.

Can I simply start using graphql-relay to begin rendering my data into a React/RN application?

On the server-side, that's definitely all you need! For your React applications, it's helpful to use the client version of Relay called react-relay which provides helpful utilities for defining the queries that each component needs satisfied in order to render.

Is there a recommended method to test my relay architecture?

That's a great question, especially when it comes to testing out mutations. Unfortunately, since GraphQL can sit in a variety of places in your stack it makes recommendations challenging.

After going through some projects now with GraphQL, integration tests can definitely be some of the more valuable tests that you can write to verify that your server is behaving the way that you expect it to. For example, when writing Mutations you might want to verify the behavior of your system when the client sends bad/no arguments, or what to do if internal errors occur.

Hope the above answers help, and thanks again for watching the course!

In reply to Austin Witherow
Avatar
EBIA

One of the best Egghead videos, great work, thank you. The clear pronunciation and the fast typing of repetitive source code make this video really appreciative (I hope, that's the correct translation of "genüsslich" from German).

Using GraphQL on production servers (security & co) would be a fantastic addition,..

Avatar
Josh Black

Hi EBIA! Just wanted to say thank you for watching, and thank you so much for the kind words! I'm glad it was helpful 😄

Definitely agree on the topic suggestion, we'll see what we can do!

In reply to EBIA

In our existing schema we have this route mutation type and it has a single field called CreateVideo that has a video type. It takes in some arguments and then resolves with a CreateVideo method.

While this worked in previous examples, in Relay there's a common pattern for mutations where they exist on the route field. The input for each mutation is a single argument called input. There are some other technical requirements as well to make mutations a little bit more predictable.

We can update this existing mutation field to be relay-compliant by first grabbing a function from GraphQL relay. In this case we're going to get mutation with client mutation ID.

Next up let's actually go and define our video mutation. I'll hop back down to the end of the file and go right above our mutation type. Here we'll say constant video mutation. It's going to be equal to calling mutation with client mutation ID and then passing in an object.

This object takes in a couple of fields, namely name, which in this case will be AddVideo. It'll also take in input fields as an object, output fields as an object, then finally a method called mutate, and GetPayload, which is going to be a method that takes in some arguments. In our case we're going to return a promise.

Input fields in this case will describe what fields are defined on our input object type, and so we can just grab the fields that we were defining on our VideoInput type. We'll grab all of these and then we can just put them inside of the input fields here. We'll go and delete the VideoInput type.

Output fields in this case will correspond to what we can actually query on after the mutation. In this case we'll just write out video and the video field will have a type of VideoType. We can actually query on the created video after our mutation.

The last part here is to fill out mutate and getPayload. Here the arguments being passed in will just correspond to whatever our input fields are. In this case we can just do promise.resolve and we can call our CreateVideo method and pass in the arguments.

When we're done we'll get a single video and what we can do is resolve and we'll pass in an object. One of the fields will be video on there. If we have any kind of errors we'll just reject.

The value that we end up returning or resolving from this method is what we're going to be able to pick out information from for these output fields. In our case if we want to be able to get the data under the video field here that's why we're resolving with an object and one of the keys on that object is video.

Our last step here is to update our mutation type. Instead of having this config object for the CreateVideo field now we'll just have video mutation.

Let's go see how our new mutation works in graphical. We'll run our server using node and then index.js. We'll bring in our graphical tool and just refresh. Now when we write our mutation we could write mutation and AddVideo query.

For the input, it's going to be the AddVideoInput. In this case AddVideoInput corresponds to the name of our mutation, which is AddVideo and then it appends input at the end.

We'll also need to make sure that this AddVideoInput part is required. We'll just add an exclamation mark after that to say that it's non-null. Inside of the mutation we'll just use CreateVideo, which will take in an input and in this case it'll be the variable input and then we can query on the video and get the title.

Let's go and add the query variables now. We'll have the object. We'll have input, which has a title. In this case we'll just say VideoTitle. We'll also have duration, which will be 300. We'll have release, which will be false. Finally we'll have ClientMutationID, which in this case for us will be ABCD.

Let's run our mutation now. We'll click execute and now we see that we have our video created and we can query on the resulting video and get the title. You can also write another query just to verify this. We could say AllVideos query.

Here we'll query on videos and go through the edges and for each node we'll get the title. When we execute that we can see that our video was actually added to our list of videos.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?