Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do we combine mutations from multiple components? #1461

Closed
witbybit opened this issue Dec 1, 2016 · 5 comments
Closed

How do we combine mutations from multiple components? #1461

witbybit opened this issue Dec 1, 2016 · 5 comments

Comments

@witbybit
Copy link

witbybit commented Dec 1, 2016

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.

@yachaka
Copy link
Contributor

yachaka commented Dec 3, 2016

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')}
      }
    `,
  },
});

@josephsavona
Copy link
Contributor

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.

@witbybit
Copy link
Author

witbybit commented Dec 4, 2016

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?

@josephsavona
Copy link
Contributor

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.

@wincent
Copy link
Contributor

wincent commented Jan 31, 2017

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants