Relay: How do we combine mutations from multiple components?

Created on 1 Dec 2016  路  5Comments  路  Source: facebook/relay

I am new to Relay and I am still trying to get more familiar with the idea of using mutations. In my use case, I have a form made up of several React components and I want to capture the mutation of each component, combine them in the parent component and then commit the changes to GraphQL server. How can I do this?

The examples that I have seen so far all deal with the mutation being used and committed in a single component. I want to use the same pattern that is used for querying where fragments are localised within the react component and then they are combined to create a query for server.

Most helpful comment

Hey @nikhilag,
For that, you can first store data changes of your form child components in the parent component state. For example, let's assume a DatePicker component inside the form :

class MyParentComponent extends Component {
  state = {
    newDate: null,
  }

  commit() {
    this.props.relay.commitUpdate(
      new UpdateMutation({
        fragment: this.props.myFragment,
        newData: {
          date: this.state.newDate,
        },
      })
    );
  }

  setDate = (newDate) => {
    this.setState({ newDate });
  }

  render() {
    return (
      <form>
        <MyDatePicker
          onChange={this.setDate}
        />
      </form>
    );
  }
}

const MyParentComponentContainer = createContainer(MyParentComponent, {
  fragments: {
    myFragment: () => Relay.QL`
      fragment on MyType {
        ${UpdateMutation.getFragment('fragment')}
      }
    `,
  },
});

All 5 comments

Hey @nikhilag,
For that, you can first store data changes of your form child components in the parent component state. For example, let's assume a DatePicker component inside the form :

class MyParentComponent extends Component {
  state = {
    newDate: null,
  }

  commit() {
    this.props.relay.commitUpdate(
      new UpdateMutation({
        fragment: this.props.myFragment,
        newData: {
          date: this.state.newDate,
        },
      })
    );
  }

  setDate = (newDate) => {
    this.setState({ newDate });
  }

  render() {
    return (
      <form>
        <MyDatePicker
          onChange={this.setDate}
        />
      </form>
    );
  }
}

const MyParentComponentContainer = createContainer(MyParentComponent, {
  fragments: {
    myFragment: () => Relay.QL`
      fragment on MyType {
        ${UpdateMutation.getFragment('fragment')}
      }
    `,
  },
});

Great question. As @yachaka answered, a straightforward approach would be to accumulate all of the changes from child components in a parent component (using callbacks and local state or something like Redux) and then make a single mutation when the user saves/commits the changes.

One pattern is to use applyUpdate to optimistically apply each individual change, then roll all those optimistic mutations back when applying the final mutation.

Thanks a lot @yachaka and @josephsavona.

@josephsavona I am trying to understand the second part you mentioned. I read that applyUpdate will give me a RelayMutationTransaction which can be committed or rollbacked. If I understand you correctly, I will need to use Redux approach (or something similar) to accumulate all the changes along with all the RelayMutationTransaction objects that I get by calling applyUpdate for changes in each component. Before committing the final mutation with all changes in the parent component, I will need to rollback all the RelayMutationTransaction objects.

Is this correct? Does it also mean that I will have to create small mutation types for each component and then combine them in the final mutation type?

Yup, that's the idea. Excerpt that you can probably just define a single mutation field/type in your schema (e.g. editFoo(input: ...) { foo }) and then each of the optimistic updates would just update different fields on the foo object in the response.

Going to close this on the assumption that the comments so far have been sufficient to unblock you. Please comment again if you have any further questions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jstejada picture jstejada  路  3Comments

rayronvictor picture rayronvictor  路  3Comments

sgwilym picture sgwilym  路  4Comments

sibelius picture sibelius  路  3Comments

fedbalves picture fedbalves  路  3Comments