How to defer useFetch/useAsyncData properly with reactive body or options
The Nuxt3 useFetch
and useAsyncData
composables are really great.
They allow us to fetch data in various scenarios and are widely customizable through all their options.
In an application we developped, we wanted to improve a form to display a loading status on the submit button when the request is performed against our API.
So here was the starting point of our component template and script setup:
<template>
<input name="pseudo" v-model="pseudo" />
<button @click="sendForm" />
</template>
<script setup>
const pseudo = ref('')
function sendForm() {
const {data, error} = useFetch('api/register', {method: 'post', body: {pseudo}})
}
</script>
The problem with this implementation is that we cannot use the status
of our request returned by the useFetch
composable to display it inside our template, because it only lives temporarily inside our sendForm
function.
So the first step to get the status
of our request was to "prepare" it at the root level and gets both the status
and the execute
handler to call it later.
<template>
<input name="pseudo" v-model="pseudo" />
<button @click="sendForm"
<!-- Attaching a class to display the request pending status -->
:class="{
loading: status === 'pending'
}"
/>
</template>
<script setup>
const pseudo = ref('')
// Reactive status vvvv vvv execute callback renamed to sendForm
// vvvvvv vvvvvv vvvvvvvv
const {data, error, status, execute: sendForm} = useFetch(
'api/register', {
method: 'post',
body: {pseudo},
// immediate option should be set to false to
// disable the useFetch auto-execution
// of the request on component setup
immediate: false
})
</script>
Now we can display our loading status, great!
But we still have a problem: the default behaviour of useFetch
is to execute the request anytime a reactive property in the url or params is updated.
Due to that, anytime we update the pseudo, the form is sent, damn it!
Fortunately, useFetch
and useAsyncData
allow us to disable this feature just by passing the watch
option to false
.
<script setup>
const pseudo = ref('')
const {data, error, status, execute: sendForm} = useFetch(
'api/register', {
method: 'post',
body: {pseudo},
immediate: false,
// Disable the auto-refreshing data when pseudo reactive updates
watch: false
})
</script>
Now we can achieve what we wanted: we can use both the status
reactive inside our template to display a loading status on our submit button and attach the execute
handler to the @click
event to send the form only when the user needs it.
Comments
Be the first to post a comment!