2

I have two mutations:

  • const [createRecord, {data}] = useMutation(createRecordQuery); which returns the ID of the newly created record
  • const [saveValue, {data: dataSave}] = useMutation(saveValueQuery); which save some values on a record

My saveValue mutation requires a record ID. If I open my form on a new record, I don't have this ID yet, so on submit I need to call createRecord first to retrieve the ID and then saveValue to save values on my record.

This simple approach doesn't work:

const onSave = async values => {
    if (!recordId) {
         // Call createRecord to retrieve recordId (code is simplified here) 
         const recordId = await createRecord();
    }

    // Save my values
    return saveValue({variables: {recordId, values});
}

But I don't really know how should I deal with the loading and data of the first mutation and wait for it to run the second mutation.

Thanks!

Tdy
  • 863
  • 12
  • 28

2 Answers2

3

The mutate function returns a promise that resolves to the mutation response data, so you should simply be able to use to achieve what you want.

From the source code:

If you're interested in performing some action after a mutation has completed, and you don't need to update the store, use the Promise returned from client.mutate

I'm not sure why this didn't work in your initial tests, but I tried it locally and it works as expected. You should essentially be able to do what you wrote in your question.

Alex Broadwin
  • 1,288
  • 11
  • 23
  • Unfortunately, this is not as straightforward as it seems.For the `saveValue` mutation, I need the recordId AND the submitted values. The only way I found to pass it into the `onCompleted` function is to use a hook state `const [valuesToSave, setValuesToSave] = useState([]);` and use that is a function that executes my `saveValue` mutation – Tdy Sep 10 '19 at 09:44
  • 1
    In that case, you could use the update option which is passed in alongside the variables. It's real purpose is to allow you to update the apollo store (eg. add the data from your mutation to other queries to avoid the need to refetch), but it should be serviceable for this as well. Like onCompleted it will provide the data from your mutation as an argument. I've updated my answer to include details. – Alex Broadwin Sep 10 '19 at 15:23
  • I accept your answer, for the `update` part. It's a bit hacky as we take advantage of something not designed for that purpose, but it makes the job. IMHO, having a simple way to chain mutations and pass data from one to the other is a lack in Apollo – Tdy Sep 11 '19 at 11:02
  • Actually, I just double-checked the source code and saw the comment 'If you're interested in performing some action after a mutation has completed, and you don't need to update the store, use the Promise returned from `client.mutate`'. I then tested using await on the mutation function and did succeed in getting the result data. Where did your attempt at that approach fail for you, exactly? – Alex Broadwin Sep 11 '19 at 15:43
  • You're totally right, it works with a simple `await` on the mutate function... I thought I tried this in the first place, I probably missed something. Thank you! – Tdy Sep 16 '19 at 14:19
  • Thanks for the update! I've updated the answer to reflect it. – Alex Broadwin Sep 16 '19 at 14:29
0

I'm not sure if there is a way to postpone execution(as well as we cannot pause <Mutation>). So how about moving second part into separate useEffect?

const [recordId, setRecordId] = useState(null);
const [values, setValues] = useState({});
const onSave = async _values => {
    if (!recordId) {
         // Call createRecord to retrieve recordId (code is simplified here) 
         setRecordId(await createRecord());
    }
    setValues(_values);
}
useEffect(() => {
  saveValue({variables: {recordId, values});
}, [recordId, _values]);

Another workaround is utilizing withApollo HOC:

function YourComponent({ client: { mutate } }) {
 onSave = async values => {
   let recordId;
   if (!recordId) {
     recordId = await mutate(createRecordQuery);
   }
   await mutate(saveValueQuery, values);
   // do something to let user know saving is done
 };

export withApollo(YourComponent);
skyboyer
  • 22,209
  • 7
  • 57
  • 64