How to migrate useAsync + error to nuxt-bridge (useAsyncData is not available)

1k views Asked by At

I'm trying to migrate a nuxt 2 app to nuxt-bridge.

In this app I frequently fetch data from an API based on URL parameters of the frontend. Like this (simplified):

  setup() {
    const { $axios, error, params } = useContext()

    const foo = useAsync(async () => {
      try {
        return await $axios.$get(`...${params.value.foo}`)
      } catch () {
        error({ statusCode: 404, message: 'Not found' })
      }
    })

    return { foo }
  }

This "tiny" limitation that useAsyncData is not available hits me pretty hard.

If I get it right, I would have to use useLazyAsyncData instead and handling pending and error states in my template. Which means I have to wrap all my current templates with something like:

<div v-if="pending">
... show something while loading ...
</div>
<div v-else-if="error">
... show error page - not even sure how to do this as my error page is based on a different layout ...
</div>
<div v-else>
... current template ...
</div>

That means:

  • I cannot properly respond with a HTTP 404 code.
  • When I finally move to nuxt3 I would have to revert all that again.

Is that correct? Is there a better way to do it?

2

There are 2 answers

0
thisismydesign On

Yes, the migration path you proposed with useLazyAsyncData is correct. Another option is not using the Composition API yet and sticking to Nuxt 2's asyncData.

2
Chanjin  Park On

I also got this problem. I solved this by creating <HttpError /> component like below

<script lang="ts" setup>
import { createError } from 'h3';

const { statusCode = 404, statusMessage = 'Not Found' } = defineProps<{
  statusCode: number;
  statusMessage: string;
}>();
throw createError({ statusCode, statusMessage });
</script>

and used it

<script lang="ts" setup>
import HttpError from '~/components/HttpError';
const { data, error } = useLazyAsyncData(...);
</script>
<template>
  <div>
    <HttpError v-if="error" :status-code="404" />
    <div v-else>
      ...
    </div>
  </div>
</template>