How to handle errors when using useAsyncData?
I've spent a bit of time researching error handling with useAsyncData and I've found very little on this subject. In my app I have a page which views an article list. When a user clicks an article it navigates to a single article view using the article id. I use the following code to retrieve the article:
<script setup lang="ts">
import type { Article } from '~/types'
const route = useRoute()
const { findOne } = useStrapi()
const { data: article, error } = await useAsyncData('article', () =>
findOne<Article>('articles', +route.params.id, {
populate: { hero: true },
}))
</script>
If I try to retrieve an invalid article using the API direct with http://localhost:1337/api/articles/2 I receive a 404 and a response:
{
"data": null,
"error": {
"status": 404,
"name": "NotFoundError",
"message": "Not Found",
"details": {}
}
}
But when I inspect the error object from the above code using console.log('error:', JSON.stringify(error)) I get in response:
{
"_object": {
"article": {
"message": "",
"statusCode": 500
}
},
"_key": "article",
"__v_isRef": true
}
I would expect the error object to contain the same 404. and perhaps a message Not Found. Why would I receive a 500?
Also, how should I manage an error in the template? Should I use a v-if to hide the content area or perform a redirect to articles? If I use a v-if should it be conditional on a property of the error object or on the data itself?
Same problem, did you solve it?
Same question. I tried wrapping findOne with try ... catch, but failed to catch the raw error of strapi.
So I found out the strapiClient source code, it does not throw strapi raw error but passes the error to strapi:error hook.
We can only get the raw error in strapi:error hook, maybe we should detect if data is null inside page then display 404, for other error then toast message in hook.
Understanding this issue is old but still open, the ship has probably sailed on the original problem here, but maybe we can shed some light on it. I don't believe this is a problem with the nuxt/strapi module, but more of an issue with how you're handling Nuxt Errors in your component.
What looks to be happening is Nuxt is encountering an error while processing your asyncData request but you're not really passing along the error from the Strapi backend through to your component. So it just says "hey there was a server error", hence the generic 500 error you're getting.
I tend to use the composable pattern for fetching data from a backend API in Nuxt. I create a composable in my root project's 'composables' folder called something like "useMyData.ts" with the nuxt/strapi module call like this:
export default async function () {
const { find } = useStrapi();
try {
const response = await find("strapiCollection", {
populate: ["*"],
sort: ["title"],
});
return (response.data)
} catch (e) {
throw createError({
statusCode: e.error.status,
statusMessage: e.error.name,
message: e.error.message,
});
}
}
Then in the component, I put my useAsyncData function and handle any errors passed along by my composable within the component.
<script setup>
const getData = useMyData();
const {
data,
error,
pending,
} = await useAsyncData("myUniqueAsyncKey", async () => {
return await getData;
});
// handle any errors from the composable and pass along the error data into my thrown error
if (error.value) {
throw createError({
statusCode: error.value?.statusCode,
statusMessage: error.value?.statusMessage,
message: error.value?.message,
});
}
</script>
<template>
<div>{{ data }}</div>
</template>
This pattern seems logical to me and definitely works for me, I use it in several projects.
It will also utilize your custom error page if you configure the error.vue component in your pages.
See the Nuxt error handling documentation here for a reference on how to handle Nuxt errors:
Also have a look at guide for the useAsyncData composable. Its a bit of a read but worth looking into the resources on that page, especially the videos by Alex Lichter, they really helped me wrap my head around it.
To answer your question if you should use "v-if" in your template, that is not necessary since you'll be redirected to your error page as soon as your error is thrown, and you can handle rendering your error nicely there for the user.