Search code examples
javascriptreactjsgraphqlapolloapollo-client

accessing data, loading, and error with mutations using variable object


I have two different mutation in the same react component:

const [get_items, { error, loading, data }] = useMutation(GET_ITEMS);

const [add_to_cart] = useMutation(ADD_TO_CART);

One way I can get both of the components error, loading, and data is like the following:

 const [get_items, { error, loading, data }] = useMutation(GET_ITEMS);

 const [add_to_cart, { error: error1, loading: loading1, data: data1 }] =
    useMutation(ADD_TO_CART);

However a more clean way that I would like to do instead if possible is the variable object way I found in this post on useQueries.

This method works in another one of my components where I am using multiple queries like the following (data can be accessed via dot notation):

  const getMany = useQuery(GET_ALL_FEILDS, {
    variables: { itemId: itemID },
    skip: location.state,
  });

  const getSome = useQuery(GET_SOME_FEILDS, {
    variables: { itemId: itemID },
    skip: !location.state,
  });

  if (getMany.loading || getSome.loading) {
    return <div>Loading...</div>;
  }

I would like to use that aproach in my mutations however I am unable to access the data that way and one thing I have tried was to remove the brackets from the add_to_cart and then try accessing add_to_cart.loading etc for example (as it was already not working in brackets), however this made the code not run at all so it did not work in either case:

  const [add_to_cart] =
    useMutation(ADD_TO_CART);

console.log(add_to_cart.loading)

or

const add_to_cart =
        useMutation(ADD_TO_CART);
    
    console.log(add_to_cart.loading)

Update:

The function I am trying to run that works only when add_to_cart is in brackets:

const addToCartFunc = async (e, user, item) => {
  e.preventDefault();
  if (user) {
    add_to_cart({
      variables: {
        user: user,
        item: item,
      },
    });
  
  }
};

Solution

  • From the docs:

    Unlike useQuery, useMutation doesn't execute its operation automatically on render. Instead, you call this mutate function.

    ... which means that we can't use it in the same way that we use useQuery.

    However, the docs also go on to say:

    When your component renders, useMutation returns a tuple that includes: A mutate function that you can call at any time to execute the mutation... An object with fields that represent the current status of the mutation's execution (data, loading, etc.)

    This means that the response of useMutation looks something like the following:

    [
      function mutation() { },
      {
        data: ...,
        loading: ...,
        //etc
      }
    ]
    

    So, if you don't want to use destructuring assignment and would instead prefer dot notation, it gives you this type of pattern:

    const get_items = useMutation(GET_ITEMS);
    
    console.log(get_items[0]); //this is get_items in your code
    console.log(get_items[1].error); //this is error in your code
    console.log(get_items[1].loading); //this is loading in your code
    console.log(get_items[1].data); //this is data in your code
    
    const add_to_cart = useMutation(ADD_TO_CART);
    
    console.log(add_to_cart[0]); //this is add_to_cart in your code
    console.log(add_to_cart[1].error); //this is error1 in your code
    console.log(add_to_cart[1].loading); //this is loading1 in your code
    console.log(add_to_cart[1].data); //this is data1 in your code