# Data Fetching

Nuxt provides `useFetch` and `useAsyncData` to handle data fetching within your application.

## `useAsyncData`

Within your pages, components and plugins you can use `useAsyncData` to get access to data that resolves asynchronously.

### Usage

```js
useAsyncData(key: string, fn: () => Object, options?: { defer: boolean, server: boolean })
```

* **key**: a unique key to ensure that data fetching can be properly de-duplicated across requests
* **fn** an asynchronous function that returns a value.
* **options**:
  * _defer_: whether to load the route before resolving the async function (defaults to `false`)
  * _server_: whether the fetch the data on server-side (defaults to `true`)
  * _transform_: A function that can be used to alter fn result after resolving
  * _pick_: Only pick specified keys in this array from fn result

Under the hood, `defer: false` uses `<Suspense>` to block the loading of the route before the data has been fetched. Consider using `defer: true` and implementing a loading state instead for a snappier user experience.

### Example

```js [server/api/count.ts]
let counter = 0
export default () => {
  counter++
  return JSON.stringify(counter)
}
```

```vue [app.vue]
<script setup>
const { data } = await useAsyncData('count', () => $fetch('/api/count'))
</script>

<template>
  Page visits: {{ data }}
</template>
```

## `useFetch`

Within your pages, components and plugins you can use `useFetch` to get universally fetch from any URL.

This composable provides a convenient wrapper around `useAsyncData` and `$fetch` and automatically generates a key based on url and fetch options and infers API response type.

### Usage

```ts
useFetch(url: string, options?)
```

Available options:

* `key`: Provide a custom key
* Options from [ohmyfetch](https://github.com/unjs/ohmyfetch)
  * `method`: Request method
  * `params`: Query params
  * `baseURL`: Base URL for request
* Options from `useAsyncData`
  * `defer`
  * `server`
  * `pick`
  * `transform`

### Example

```vue [app.vue]
<script setup>
const { data } = await useFetch('/api/count')
</script>

<template>
  Page visits: {{ data.count }}
</template>
```

### Best practices

The data returned by `useAsyncData` will be stored inside the page payload. This means that every key returned that is not used in your component will be added to the payload.

::alert{icon=👉}
**We strongly recommend you only select the keys that you will use in your component.**
::

Imagine that `/api/mountains/everest` returns the following object:

```json
{
  "title": "Mount Everest",
  "description": "Mount Everest is Earth's highest mountain above sea level, located in the Mahalangur Himal sub-range of the Himalayas. The China–Nepal border runs across its summit point",
  "height": "8,848 m",
  "countries": [
    "China",
    "Nepal"
  ],
  "continent": "Asia",
  "image": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Everest_kalapatthar.jpg/600px-Everest_kalapatthar.jpg"
}
```

If you plan to only use `title` and `description` in your component, you can select the keys by chaining the result of `$fetch` or `pick` option:

```vue
<script setup>
const { data: mountain } = await useFetch('/api/mountains/everest', { pick: ['title', 'description'] })
</script>

<template>
  <h1>{{ mountain.title }}</h1>
  <p>{{ mountain.description }}</p>
</template>
```

### Using async setup

If you are using `async setup()`, the current component instance will be lost after the first `await`. (This is a Vue 3 limitation.) If you want to use multiple async operations, such as multiple calls to `useFetch`, you will need to use `<script setup>` or await them together at the end of setup.

::alert{icon=👉}
Using `<script setup>` is recommended, as it removes the limitation of using top-level await. [Read more](https://v3.vuejs.org/api/sfc-script-setup.html#top-level-await)
::

```vue
<script>
export default defineComponent({
  async setup() {
    const [{ data: organization }, { data: repos }] = await Promise.all([
      useFetch(`https://api.github.com/orgs/nuxt`),
      useFetch(`https://api.github.com/orgs/nuxt/repos`)
    ])

    return {
      organization,
      repos
    }
  }
})
</script>

<template>
  <header>
    <h1>{{ organization.login }}</h1>
    <p>{{ organization.description }}</p>
  </header>
</template>
```
