Search code examples
reactjsgraphqlapollomutation

Mutation called returns false, but the object is created in DB


I've built a modal in ReactJS and added handleClick on submit button.

    const handleSubmit = async (event) => {
    event.preventDefault();
    const res = await createApp({variables: {id, name, url}});
    console.log('response' + res)
    console.log('loading' + loading);
    console.log('called' + called);
    console.log('error' + error)
    console.log('data' + data)
  }

On the first click, I'm getting

 response[object Object]
 loadingfalse
 calledfalse
 errorundefined
 dataundefined

On the second click, I'm getting

response[object Object]
loadingfalse
calledtrue
errorundefined
data[object Object]

However, the right object is being created in DB on the first click!


Solution

  • It's not clear from your question how you're getting the loading, error, called and data variables, but I'll assume it's from the useMutation hook. However, if you're using the Mutation component, the following explanation still applies.

    The useMutation hook returns an array with a function and a MutationResult object, which includes properties like loading, error, called and data. These properties are exposed as a convenience in order to easily update your component's UI, however, they are just regular component state. As such, any changes to them are asynchronous, just like with setState.

    In other words, you can call and await createApp and as a result of doing so, the aforementioned properties will be eventually updated. However, there is no guarantee that they will updated before the Promise returned by createApp resolves. So even though you're awaiting the call to createApp, the values of each of those properties have not updated yet. If, instead of logging them inside the click handler, you instead render them inside your component, you will seem them change appropriately.

    If you need to access the data returned by your operation inside the click handler, you can do so from the value of the resolved Promise:

    const { data, error } = await createApp({variables: {id, name, url}});
    
    // Note: loading and called are not exposed similarly because that would be moot --
    // if the promise has resolved, the function was called and you're no longer loading