Closed evgenii-code closed 1 year ago
Sorry, Composables that block Navigation like asyncData cannot be implemented in nuxt 2. refs: https://github.com/nuxt-community/composition-api/issues/596#issuecomment-1008972575
As a side note, asyncData can also be used in Nuxt 3. https://nuxt.com/docs/api/utils/define-nuxt-component#asyncdata
@wattanx
Thank you for the quick response and provided recources,
I get that we can't block navigation with composition API in Nuxt 2.
But I think my original question was formulated incorrectly.
I want to get an error from the response, because I see the HTML rendered on the server with an error.
I was wondering, is there some kind of a hook triggering after useLazyAsyncData
finishes that I can intercept error on server side?
Like
const { hook } = useNuxtApp();
const { data } = useLazyAsyncData(...);
hook('whatever:hook', ssrErrorHandler);
This is my approach to handle error on my own, but it feels wrong.
Maybe I should give up and use Options API instead
<script setup>
const { $axios } = useNuxtApp()
const { data, pending } = useLazyAsyncData('fetch-todos', async () => {
try {
return {
response: await $axios.$get(
'https://jsonplaceholder.typicode.com/todos/-1'
),
error: null,
}
} catch (error) {
return { response: null, error }
}
})
</script>
Create composable lib/page-error-handler.ts
:
import type { NuxtError } from '#app/composables/error'
export const useHandlePageError = (error: Ref<NuxtError | null>) => {
// universal way to handle serverside and clientside error
// https://www.reddit.com/r/Nuxt/comments/17coll0/comment/kg4syhv/
watch(error, (value) => {
if (!value) { return }
throw createError({
statusCode: error.value?.statusCode || 400,
message: error.value?.data?.message || error.value?.message || 'Something went wrong',
fatal: true,
})
}, { immediate: process.server })
}
Then use it on your page:
<template>
<!--
add if condition because data is a nullable ref,
when execute on clientside with error (or while pending)
it has null value
-->
<div v-if="data">{{ data }}</div>
</template>
<script setup>
import { useHandlePageError } from '~/lib/page-error-handler'
const { data, error } = await useLazyAsyncData('my_page', async () => {
// fetch your data
})
/*
In client execution we will get here immediately,
because `lazy` does not wait for the request to be executed.
The error will initially have a null value, and only after
the request is completed then the error will get its value.
Therefore `watch(error)` is used
In server execution lazy is ignored, and we will get
here only after the request is executed,
therefore immediate is used for the server variant
*/
useHandlePageError(error)
</script>
Environment
Reproduction
Repository https://github.com/evgenii-code/nuxt-bridge-error-page
Reproduction in sandbox
https://codesandbox.io/p/sandbox/nuxt-bridge--uselazyasyncdata-with-error-ddcrgq
Describe the bug
I want to redirect to an error page when an error occurs by fetching data with
useLazyAsyncData
composable.We can't use
await useLazyAsyncData
in<script setup>
with Vue 2 and the data is fetching inlazy
mode. So the redirect happens only on client side, whenerror.value === true
There you can see how redirect occurs only on client side -- background flashes for a moment.
Video reproduction https://codesandbox.io/p/sandbox/nuxt-bridge--uselazyasyncdata-with-error-ddcrgq
It is mandatory to redirect on server side to the error page if an error occurs. I can't understand how to achieve this behavior
Additional context
I can achieve wanted behavior by using
asyncData
in the Options API, but since we want to update out project to Nuxt 3, we want to use Composition API.Logs
No response