nuxt: on initial client side load with `server: false`, useFetch does not await data fetching

Environment

Operating System: Darwin Node Version: v17.2.0 Nuxt Version: 3.0.0-27491748.3186841 Package Manager: yarn@1.22.10 Builder: vite User Config: - Runtime Modules: - Build Modules: -

Reproduction

https://codesandbox.io/s/unruffled-rain-zzuixq?file=/app.vue

Describe the bug

When using useFetch composable inside setup method or inside any lifecycle hook then it directly shows error. It does not even hit the backend api.

Additional context

No response

Logs

RefImpl {
  __v_isShallow: false,
  dep: undefined,
  __v_isRef: true,
  _rawValue: null,
  _value: null
}
RefImpl {
  __v_isShallow: false,
  dep: undefined,
  __v_isRef: true,
  _rawValue: null,
  _value: null
}

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 3
  • Comments: 24 (11 by maintainers)

Most upvoted comments

Although it’s already mentioned in documents, I would like to share some ideas for clearer logic.

In this case I use watch() to watch whether status is updated, and I specify immediate to make sure this code will be run at least once. So no matter what ssr and server are, it should be able to process API response, correctly.

const res = await useFetch('https://nekos.best/api/v2/neko', {server: false});
watch(res.status, () => {
  if (res.status.value === 'success') {
    const v = res.data.value;
    // ...
  }
}, {immediate: true});

I am not sure if there are any other side effects, but it works on my project so far.

I agree with @siddharth223437. The main issue for me is that the call is not blocked and the response never gets updated with the payload. So, the await is pointless. For me, the call is made to the backend but just doesn’t get blocked and then the only way to get the data is to watch data. This ends up behaving like useLazyFetch, which isn’t what is expected.

Ah. If you are calling something within a method, you should almost certainly use $fetch directly rather than useFetch, which is only meant to be called in the setup method.

Same problem when nuxt is set to ssr: false: await is not waiting for useFetch() to actually fetch the data.

@cyruscollier Yes, that’s right. Or within a function immediately invoked within the setup function (a composable).

@mario-neuhold I ended up creating composable which is a wrapper on $fetch

import { useRuntimeConfig } from ‘nuxt/app’ import {$fetch} from “ohmyfetch”;

composable/useMyFetch.ts

export const useMyFetch = async (req: string, opts?) => {
  const config = useRuntimeConfig()

  return $fetch(req,{
    ...opts,
    baseURL: config.aisAuth.client.baseUrl,
    headers: {
      Accept: 'application/json',
    },
    credentials: 'include',
    async onResponse({ request, response, options }) {
      if(response.status === 401){
          // do something on 401 response
      }

    }
  }).catch((err) => ({error: err}))
}

Then you can use useMyFetch inside your .vue file

async function myFunc(){
    const resp = await useMyFetch('url')
}