Getting started with Vue Query and TypeScript
Tags: vue, javascript, webdev
Published: 2021-07-10 11:45:07

## What is Vue Query?

[Vue Query](https://github.com/DamianOsipiuk/vue-query/) provides hooks for fetching, caching and updating asynchronous data in Vue.

It is based on [React Query](https://github.com/tannerlinsley/react-query) and inherits all of its concepts from the main package.

It works in both Vue 2 with the [Composition API plugin](https://github.com/vuejs/composition-api) and Vue 3.

## Installing Vue Query

To install Vue Query, we run the following command in a terminal:

```
yarn add vue-query
```

## Using Vue Query

Vue Query requires a query provider attached in the root of our application.

```typescript
import { defineComponent } from 'vue';
import { useQueryProvider } from 'vue-query';

export default defineComponent({
  name: 'App',
  setup() {
    useQueryProvider();
  },
});
```

`useQueryProvider` provides our app an instance of the `QueryClient` class from the `react-query/core` package.

In a component that fetches data, a `useQuery` hook allows us to specify our function that fetches data:

```typescript
import { defineComponent } from 'vue'
import { useQuery } from 'vue-query';
...
export default defineComponent({
    name: 'Todos',
    setup() {
       const { data, isLoading, isError } = useQuery(
           'todos', // query key
           getTodos // fetching function
       )

       return {
            data,
            isLoading,
            isError
       }
    }
})
```

As you can see with `useQuery` the first argument is a simple string. This caches and tracks the result of that query.

The second argument is how we actually get the data. It either needs to resolve data or throw an error.

`useQuery` has generic parameters for the type of the data that is being fetched and the error type if a failure occurs:

```typescript
useQuery<Todo[], Error>(
  'todos',
  getTodos
);
```
`Error` is the standard [error object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error).

The `Todo` type is as follows:

```typescript
type Todo = {
    userId: number
    id: number
    title: string
    completed: boolean
}
```

## Fetching function

The fetching function implementation is as follows:

```typescript
async function getTodos() {
    const response = await fetch('https://jsonplaceholder.typicode.com/');
    return response.json();
}
```

## Finishing the component

Here’s the rest of the component implementation:

```html
<template>
    <div v-if="isLoading">Loading...</div>
    <div v-else-if="isError">{{ error!.message }}</div>
    <div v-else>{{ JSON.stringify(data) }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { useQuery } from 'vue-query'

type Todo = {
    userId: number
    id: number
    title: string
    completed: boolean
}

export default defineComponent({
    name: 'Todos',
    setup() {
       const { data, isLoading, isError, error } = useQuery<Todo[], Error>(
           'todos',
           getTodos
       )

       return {
            data,
            isLoading,
            isError,
            error
       }
    }
})
</script>
```

After the first request, the response will be instant because we're using cached data.

If you’re interested to learn more, don’t forget to check out the [Vue Query documentation](https://vue-query.vercel.app/) and the [React Query documentation](https://react-query.tanstack.com/).