Breaking app when awaiting composable in page setup
I have a pretty barebones use case that seems like it shouldn't be breaking things.
On my page setup, I do the following:
In my composables:
This causes the dreaded
A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function.
error. I tried some of the workarounds, but was not successful. What am I missing here?4 Replies
Hi @dmarr. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
The issue you're encountering is related to how Nuxt handles asynchronous operations in the setup function and composables. Let's break down the problem and provide a solution based on the knowledge sources.
The error message you're seeing is a common one in Nuxt 3 when dealing with asynchronous operations and composables. The root cause is that when you
await
a composable directly in the setup function, it can lead to losing the Nuxt context, which is essential for composables to work correctly.
Here's how we can fix this issue:
1. Instead of awaiting the composable directly, use the useAsyncData
composable to handle the asynchronous operation.
2. Move the useFetch
call directly into the setup function or into the useAsyncData
handler.
Here's the corrected code for your page:
And your composables can be simplified to:
This approach ensures that the Nuxt context is maintained throughout the asynchronous operation.
The reason for this behavior is explained in the Nuxt 3 documentation on auto-imports:
During a component lifecycle, Vue tracks the temporary instance of the current component (and similarly, Nuxt tracks a temporary instance of nuxtApp
) via a global variable, and then unsets it in same tick. This is essential when server rendering, both to avoid cross-request state pollution (leaking a shared reference between two users) and to avoid leakage between different components.
By using useAsyncData
, we ensure that the asynchronous operation is handled correctly within the Nuxt lifecycle.
If you need to use the useTest2
composable in multiple places, you can refactor it to use useAsyncData
internally:
Then in your component, you can use it like this:
This approach maintains the composable pattern while ensuring proper context handling in Nuxt 3.
Nuxt 3 Documentation: Auto-imports provides more details on this behavior and best practices for using composables in Nuxt 3.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@139883350096740354> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@dmarr The warning in the docs stipulates: “do not await useFetch in a composable, as that can cause unexpected behavior”
The issue arising here is that you’re wrapping useFetch in a promise, and awaiting that promise, when it is expected that the promise returned from useFetch is to be resolved in setup/plugins/middleware.
In short, do not await useFetch or useAsyncData anywhere besides the permitted locations.
ok.. thanks
I feel like for the amount of time I use nuxt, (all day, every day haha) this should have been more obvious to me. I haven't seen that part of the docs, and I scour the useFetch/custom fetch wrapper stuff pretty consistently. Maybe the error message lacks some information that could make troubleshooting easier.
The page it links to currently links to a verbose github issue with details that are no longer relevant. Ie, before certain fixes were added you had to do certain things to workaround the issue. The reason it cropped up for me was due to the reasons you said, but those weren't shown in the error...
why wouldn't this work in a composable?
I'm not using useFetch
Also this doesn't break, until I add the second useAsyncData..
I guess this works
I have literally hit every wall on the way to productivity haha