Mutations

Mutations Basics

villus offers a useMutation function that is very similar to its querying counterpart but with few distinct differences:

  • It does not accept a variables option.
  • It does not execute automatically, you have to explicitly call execute.
  • Cache policies do not apply to mutations as mutations represent user actions and will always use network-only policy.

Here is an example of the useMutation function:

vue<template>
  <div>
    <div v-if="data">
      <p>{{ data.likePost.message }}</p>
    </div>
    <button @click="execute()">Submit</button>
  </div>
</template>

<script setup>
import { useMutation } from 'villus';

const LikePost = `
  mutation {
    likePost (id: 123) {
      message
    }
  }
`;

const { data, execute } = useMutation(LikePost);
</script>

Passing Variables

Since the useMutation function does not accept a variables property you can pass them to the execute function:

vue<script setup>
const LikePost = `
  mutation LikePost ($id: ID!) {
    likePost (id: $id) {
      message
    }
  }
`;

const { data, execute } = useMutation(LikePost);

function onSubmit() {
  const variables = {
    id: 123,
  };

  execute(variables);
}
</script>

Clearing Tagged Queries Cache

To clear tagged queries’ cache, you can specify a clearCacheTags option when calling useMutation composable:

vue<script setup>
const CreatePost = `
  mutation CreatePost ($title: String!) {
    createPost (title: $title) {
      id
    }
  }
`;

const GetPosts = `
  query GetPosts {
    posts {
      id
      title
    }
  }
`;

const { data } = useQuery(GetPosts, {
  tags: ['all_posts'],
});

const { execute } = useMutation(CreatePost, {
  clearCacheTags: ['all_posts'],
});

function onSubmit() {
  execute({
    title: 'hello there',
  });
}
</script>

This will clear all the cache entries for any queries tagged with all_posts when using useQuery. The next time they are fetched they will go straight to the network and fetch the fresh data from the server.

Refetching queries after a mutation

Aside from clearing the cache for tagged queries, you can also refetch them. By specifying refetchTags option when calling useMutation composable:

vue<script setup>
const CreatePost = `
  mutation CreatePost ($title: String!) {
    createPost (title: $title) {
      id
    }
  }
`;

const GetPosts = `
  query GetPosts {
    posts {
      id
      title
    }
  }
`;

const { data } = useQuery(GetPosts, {
  tags: ['all_posts'],
});

const { execute } = useMutation(CreatePost, {
  refetchTags: ['all_posts'],
});

function onSubmit() {
  execute({
    title: 'hello there',
  });
}
</script>

After the mutation execution completes, it will trigger a refetch for all queries tagged with all_posts tag. Note that refetchTags also clear the cache if present for those tagged queries, so the refetch will always override the network policy and the cached results.

Handling Errors

You can handle errors by either grabbing the error ref returned from the useMutation function or by checking the result of the execute promise, the latter is preferable as it makes more sense in most situations. The execute function doesn’t throw and collects all encountered errors into a CombinedError instance that contains any GraphQL or network errors encountered.

vue<script setup>
const LikePost = `
  mutation LikePost ($id: ID!) {
    likePost (id: $id) {
      message
    }
  }
`;

const { data, execute } = useMutation(LikePost);
const variables = {
  id: 123,
};

function onSubmit() {
  execute(variables).then(result => {
    if (result.error) {
      // Do something
    }
  });
}
</script>

Event hooks

useMutation returns event hooks allowing you to execute code when a specific event occurs.

onData

This is called whenever a new result is available.

vue<script setup>
import { useMutation } from 'villus';

const { data, execute } = useMutation(LikePost, {
  onData: (data) => {
    // Do something
    console.log(data)
  },
});
</script>

onError

It is triggered when an error occurs.

vue<script setup>
import { useMutation } from 'villus';

const { data, execute } = useMutation(LikePost, {
  onError: (error) => {
    // Handle the error
    console.log(error)
  },
});
</script>

There are more things you can do with mutations, like displaying progress for users. Check the API documentation for useMutation.