Krzysztof Żuraw Blog

Mutations in Relay Modern

January 06, 2018

In this series, I covered various topics starting from setting up Django and ending in Relay queries. There is only one topic to be covered - mutations. And today I want to tell you how to implement them.

What is mutation

You can think of mutation of a request that changes data. In REST terms it will be POST, PUT or DELETE. In addition to this in Relay you can request your data back - It means that to display newly created entity you don’t need an additional query.

Mutation looks as follows:

mutation CreateFilmMutation($input: CreateFilmInput!) {
    createFilm(input: $input) {
      film {
        id
        title
        rating
        airDate
        actors {
          firstName
          lastName
        }
      }
    }
  }

In such case, I provide inputs to mutation. For film it will be a title, air date and rating. In definition I also add a query for getting created data back.

How to implement mutation

As I got simple mutation definition it’s time to implement it. First I need to create a way to execute my mutation. I decided to have a form where a user can fill title, air date and rating. When she or he submits - I will execute mutation. It looks as follows:

export default class AddFilmForm extends Component {
  constructor(props) {
    super(props);

    this.state = {
      title: "",
      date: "",
      rating: 0
    };
  }

  handleChange = event => {
    const target = event.target;
    const name = target.name;
    const value =
      target.type === "select-one" ? parseInt(target.value, 10) : target.value;
    this.setState({
      [name]: value
    });
  };

  handleSubmit = () => {
    CreateFilmMutation(this.state.title, this.state.date, this.state.rating);
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <FormGroup>
          <ControlLabel>Enter details of new film</ControlLabel>
          <FormControl
            type="text"
            name="title"
            value={this.state.title}
            placeholder="Title"
            onChange={this.handleChange}
          />
        </FormGroup>
        <FormGroup>
          <ControlLabel>Enter details of new film</ControlLabel>
          <FormControl
            type="date"
            name="date"
            value={this.state.date}
            placeholder="Air date"
            onChange={this.handleChange}
          />
        </FormGroup>
        <FormGroup onChange={this.handleChange}>
          <ControlLabel>Select rating</ControlLabel>
          <FormControl
            componentClass="select"
            placeholder="select"
            name="rating"
          >
            <option value="0">0</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4">4</option>
          </FormControl>
        </FormGroup>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

As you can see this is a normal implementation of how to handle forms in React. I catch onChange events in handleChange then get value character by character and store in the component state. At the end when user clicks submit I just fire up CreateFilmMutation inside handleSubmit.

How is this mutation implemented? Look below:

import { commitMutation, graphql } from "react-relay";
import environment from "../Environment";

const mutation = graphql`
  mutation CreateFilmMutation($input: CreateFilmInput!) {
    createFilm(input: $input) {
      film {
        id
        title
        rating
        airDate
        actors {
          firstName
          lastName
        }
      }
    }
  }
`;

export default function CreateFilmMutation(title, airDate, rating) {
  const variables = {
    input: {
      title,
      airDate,
      rating,
      actors: [{ actorId: "QWN0b3I6MQ==" }]
    }
  };
  commitMutation(environment, {
    mutation,
    variables,
    onCompleted: (response, errors) => {
      console.log("Response received from server.");
    },
    onError: err => console.error(err)
  });
}

At the top, I have my mutation syntax which then will be executed at the graphql endpoint. In my variables definition I hardcode actors which can be changed by tweaking a little bit form.

As you can see a mutation in executed in commitMutation with two callbacks: one for completing mutation and the second one when mutation end with an error. This is a useful place to show for example errors to the user or some confirmation.

That’s all! I have my mutation working. Thank you for reading that and if you like it please share it on interwebs.

Repo with code can be found on Github.

Tagged with graphql relay javascript react

This blog post is part of series. Go back to previous one.


I turned off Disqus comments. If you want to give me feedback please write to krzysztof.zuraw(at)fastmail.com or use Keybase.


Krzysztof ŻurawDelivered by Krzysztof Żuraw. Opinions are my own. You can follow updates via RSS feed.