useQuery()

The useQuery function allows you to execute GraphQL queries, it requires a Provider or useClient to be called in the component tree, so make sure to set that up before using useQuery

The useQuery function returns the following properties and functions:

PropertyTypeDescription
dataRef<any/null>The GraphQL query result’s data
errorRef<CombinedError>Any errors encountered during query execution
execute({cachePolicy: CachePolicy}) => Promise<OperationResult<TData>>Executes the query and returns the operation result containing data and error values
isDoneRef<boolean>Set to true when the query is executed at least once, never resets to false
isFetchingRef<boolean>Set to true when the query is executing either by calling execute explicitly or by watch effect due to reactive variables or queries

There might be undocumented properties, such properties are no intended for public use and should be ignored.

Usage

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

const Todos = `
  query Todos {
    todos {
      text
    }
  }
`;

// without variables
const { data, error } = useQuery({
  query: Todos,
});

const FindTodo = `
  query FindTodo($id: ID!) {
    todo (id: $id) {
      text
    }
  }
`;

// with variables
const { data, error } = useQuery({
  query: FindTodo,
  variables: { id: 1 },
});
</script>

Query Options

These are the full object fields that the useQuery function accepts:

PropertyTypeRequiredDescription
querystring or DocumentNode or Ref<string>YesThe query to be executed
variablesobject or Ref<object>NoThe query variables
cachePolicyA string with those possible values cache-and-network or network-only or cache-firstNoThe cache policy to execute the query with, defaults to the value configured with the provided client
fetchOnMountbooleanNoIf the query should be executed on mounted, default is true
context{ headers: Record<string, string> }NoA object to be merged with the fetch options, currently accepts headers. The context can be a reactive ref or computed ref.
pausedboolean or Ref<boolean> or (variables?: TVars) => booleanNoWhen true it will pause executing the query when the variables change. If it is a reactive or a function and it changes back to false it will re-execute the query automatically if no execution was already in progress.
skipRef<boolean> or (variables?: TVars) => booleanNoWhen true any execution calls will be prevented. Similar to paused, except it doesn’t trigger any automatic executions when it changes.
tagsstring[]NoTags the query for cache clearing or refetching.

This signature allows you to tweak the fetchOnMount and cachePolicy behaviors for the query, Here is an example:

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

const FindTodo = `
  query FindTodo($id: ID!) {
    todo (id: $id) {
      text
    }
  }
`;

const { data, error } = useQuery({
  query: FindTodo, // query
  variables: { id: 1 }, // variables
  fetchOnMount: false,
  cachePolicy: 'network-only',
});
</script>

Reactivity

The useQuery works well with reactive arguments with some limitations

Reactive Queries

You can create reactive queries using Ref or Computed with the recommended being Computed as it is unlikely you will be explicitly changing the query value. By default useQuery detects whenever a query argument is reactive and watches it for changes, when a change is triggered it will re-fetch the query automatically.

vue<script setup>
import { computed, ref } from 'vue';
import { useQuery } from 'villus';

// computed id that will be used to compute the query
const id = ref(1);

// Create a computed query
const FetchTodo = computed(() => {
  return `query FetchTodo {
      todo (id: ${id.value}) {
        text
      }
    }
  `;
});

const { data } = useQuery({
  query: FetchTodo,
});

// later on, changing the `id` ref will automatically refetch the query because it is computed
id.value = 2;
</script>

This works the same if you are using graphql-tag and returning ASTs for your queries. But it’s unlikely you will be switching between two different queries.

reactive() Support

Note that reactive objects created with reactive() are not considered reactive queries, only Ref and ComputedRef are accepted.

Reactive Variables

You can also create reactive variables and useQuery will detect them and will be watching them for changes, once a change is detected it will re-fetch the query. You can create reactive variables with both ref or reactive and their derivatives.

Here is a quick sample with reactive:

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

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

const { data } = useQuery({
  query: `query FetchTodo ($id: ID!) {
      todo (id: $id) {
        text
      }
    }
  `,
  variables,
});
</script>

This also works with ref()

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

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

const FetchTodo = `
  query FetchTodo ($id: ID!) {
    todo (id: $id) {
      text
    }
  }
`;

const { data } = useQuery({
  query: FetchTodo,
  variables,
});
</script>

You can pause variable watching by checking the guide.

For more information on useQuery, check the queries guide