jbrown
jbrown

Reputation: 7996

How to get the ID of a new object from a mutation?

I have a createObject mutation that returns the ID of the new object.

After it returns I want to redirect to a detail page about the new object.

How can I get response fields from a mutation in the containing component using react/relay?

E.g. my createObject page contains the mutation with code like:

var onFailure = (transaction) => {

};

var onSuccess = () => {
  redirectTo('/thing/${newthing.id}');   // how can I get this ID?
};

// To perform a mutation, pass an instance of one to `Relay.Store.update`
Relay.Store.update(new AddThingMutation({
  userId: this.props.userId,
  title: this.refs.title.value,
}), { onFailure, onSuccess });
}

newthing should be the object created by the mutation, but how can I get hold of it?

Upvotes: 10

Views: 2549

Answers (1)

steveluscher
steveluscher

Reputation: 4228

Normally we would configure the client-side of the mutation with RANGE_ADD and return a new thingEdge from the server side of the mutation, but here you don't have a range on the client to add the new node to. To tell Relay to fetch an arbitrary field, use the REQUIRED_CHILDREN config.

Server side mutation

var AddThingMutation = mutationWithClientMutationId({
  /* ... */
  outputFields: {
    newThingId: {
      type: GraphQLID,
      // First argument: post-mutation 'payload'
      resolve: ({thing}) => thing.id,
    },
  },
  mutateAndGetPayload: ({userId, title}) => {
    var thing = createThing(userId, title);
    // Return the 'payload' here
    return {thing};
  },
  /* ... */
});

Client side mutation

class AddThingMutation extends Relay.Mutation {
  /* ... */
  getConfigs() {
    return [{
      type: 'REQUIRED_CHILDREN',
      // Forces these fragments to be included in the query
      children: [Relay.QL`
        fragment on AddThingPayload {
          newThingId
        }
      `],
    }];
  }
  /* ... */
}

Example usage

var onFailure = (transaction) => {
  // ...
};

var onSuccess = (response) => {
  var {newThingId} = response.addThing;
  redirectTo(`/thing/${newThingId}`);
};

Relay.Store.update(
  new AddThingMutation({
    title: this.refs.title.value,
    userId: this.props.userId,
  }), 
  {onSuccess, onFailure}
);

Note that any fields you query for by using this technique will be made available to the onSuccess callback, but will not be added to the client side store.

Upvotes: 19

Related Questions