Multiple calls to `useAsyncQuery` from composable function causes 500 error in SSR
Environment
- Operating System: Linux
- Node Version: v18.18.0
- Nuxt Version: 3.11.2
- CLI Version: 3.11.1
- Nitro Version: 2.9.6
- Package Manager: [email protected]
- Builder: -
- User Config: devtools, modules, apollo
- Runtime Modules: @nuxtjs/[email protected]
- Build Modules: -
Describe the bug
Calling useAsyncQuery more than once inside a composable function results in a 500 error when loading a SSR route, with the following error message:
[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables`.
Expected behaviour
Should be able to execute more than a single query in a composable function.
Reproduction
https://stackblitz.com/edit/github-tfy4rs?file=composables%2FuseMultipleQuery.ts
Example composable function:
export const useMultipleQuery = async () => {
const dataOne = ref();
const dataTwo = ref();
const responseOne = await useAsyncQuery(gql`
query Launches {
launches {
id
mission_name
}
}
`);
dataOne.value = responseOne.data.value;
const responseTwo = await useAsyncQuery(gql`
query Rockets {
rockets {
id
description
}
}
`);
dataTwo.value = responseTwo.data.value;
return {
dataOne,
dataTwo,
};
};
Additional context
Executing multiple queries with useAsyncQuery works as expected when inside <script setup> or loading a route in client-side context.
Logs
500
[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables`.
at useApollo (./node_modules/@nuxtjs/apollo/dist/runtime/composables.mjs:75:41)
at prep (./node_modules/@nuxtjs/apollo/dist/runtime/composables.mjs:26:23)
at Module.useAsyncQuery (./node_modules/@nuxtjs/apollo/dist/runtime/composables.mjs:16:32)
at Module.useMultipleQuery (./composables/useMultipleQuery.ts:19:51)
at async setup (./app.js:19:12)
I also ran into this. I solved it by wrapping things in useNuxtApp().runWithContext(async () => { /* my code here */ })
I think this is more like a limitation of Nuxt, perhaps? After awaiting an async call, it's like I have been transported out of the usual Nuxt context and into a then-function of a Promise. So context probably has to be re-established.
Relevant Nuxt documentation:
- https://nuxt.com/docs/guide/going-further/nuxt-app#the-nuxt-context
- https://nuxt.com/docs/api/composables/use-nuxt-app#a-deeper-explanation-of-context
- https://nuxt.com/docs/api/composables/use-nuxt-app#runwithcontext
The context is unset by Nuxt/Vue after the first await leading to the error on the second.
I think you can either use runWithContext as suggested by @filiphazardous or for for example multiple await $fetch() calls, I've wrapped them in an async handler function that I use with useAsyncData(handler, ...).