Vue & Nuxt
Vue itself does provide some basic data fetching paradigms, like the useFetch
hook and the <script>
tag.
Setup
Consider the following API router definition
import { api } from '@hulla/api'
const a = api()
export const usersAPI = a.router({
name: 'users',
routes: [
a.procedure('getAllUsers', () => db.users.get()),
a.procedure('getUserById', (id: string) => db.users.get(id))
a.procedure('example', () => fetch('https://api.com/example')),
// etc...
]
})
Note you can also use the
request
integration for type-safe requests.
The <script setup>
tag
The most basic examkple is to use a fetch call in your <script>
tag.
<script setup>
import { ref } from 'vue'
const data = ref(null)
const error = ref(null)
const fetchData = async () => {
try {
data.value = await usersAPI.call('getAllUsers')
} catch (e) {
error.value = e
}
}
</script>
<template>
<div v-if="error">Oops! Error encountered: {{ error.message }}</div>
<div v-else-if="data">
Data loaded:
<pre>{{ data }}</pre>
</div>
<div v-else>Loading...</div>
</template>
Nuxt
While the script tag is a powerful tool, for more complex applications it’s common to use an advanced solution like Nuxt.
useFetch
The most common solution is the useFetch
composable wrapper.
While I generally try to recommend not to use framework specific solutions inside the procedure definitions here it’s really up to you to decide how you want to structure your API.
- My preffed way that adheres to best practices - return
useFetch
args from the procedure
routes: [
a.procedure('getUserById', (id: string) => ['https://api.com/users/${id}'])
a.procedure('createUser', (user: User) => [
'https://api.com/users',
{ method: 'POST', body: JSON.stringify(user) }
])
]
and then
<script setup lang="ts">
import { usersAPI } from '@/api/users'
const { data: user } = useFetch(...usersAPI.call('getUserById', '123'))
</script>
<template>
<div>{{ user }}</div>
</template>
- Or add it to the procedure directly (do this if you only will fetch data through vue/nuxt)
routes: [
a.procedure('getUserById', (id: string) => useFetch(`https://api.com/users/${id}`))
]
and then
<script setup lang="ts">
import { usersAPI } from '@/api/users'
const { data: user } = await usersAPI.call('getUserById', '123')
</script>
<template>
<div>{{ user }}</div>
</template>
In an ideal scenario, there should be an adapter / integration for
vue
that would just take the procedure and transform it touseFetch
, similar how requests integration works.
$fetch
The $fetch
with useAsyncData
is pretty much identical to useFetch
, with just missing deduplicaton. Pleae refer to example above.
useAsyncData
Here the standard data fetching principles work nicely
<script setup lang="ts">
import { usersAPI } from '@/api/users'
const { data, error } = useAsyncData('getAllUsers', () => usersAPI.call('getAllUsers'))
</script>