Data Fetching Composable Advice
We have an Organization entity in our app, and each organization has related Events. We’re expecting to reuse this fetching logic across multiple parts of our app.
Fetching the organization data alone is straightforward and nicely encapsulated:
Usage in a page:
Where we’re stuck is how best to fetch and structure related event data. These events are tied to the organization.
One idea was to extend the composable like this:
Then use it like this:
This works, but by spreading the
orgResponse
, we lose the “thenable” behavior of useFetch. We’d like to keep the ability to await useOrganization(id)
in page-level usage.
So I’m wondering:
- Is this an acceptable approach?
- Should we separate event logic into its own composable (e.g., useOrganizationEvents(id)
)?
- Is there a clean way to preserve the thenable behavior while extending the returned object?
Any best practices, patterns, or anti-patterns to consider would be much appreciated!5 Replies
Hi @Matt. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Your approach is thoughtful, but there are some best practices and Nuxt-specific patterns to consider for composable design and data fetching, especially when dealing with related data from different APIs.
1. Separation of Concerns: Use Separate Composables
The recommended pattern in Nuxt is to keep composables focused and reusable. Since events are a distinct resource (and come from a different API), it’s best to create a separate composable for fetching organization events, e.g.,
- Use separate composables for organization and events. - Don’t spread/extend the result of
useOrganizationEvents(id)
. This keeps your logic modular, easier to test, and more flexible for future changes or reuse elsewhere in your app.
Example:
Usage:
This approach aligns with Nuxt’s best practices for composables and avoids coupling unrelated fetching logic together [Nuxt useFetch API docs].
2. Preserving Thenable Behavior
When you spread the result of useFetch
(or useAsyncData
), you lose the thenable/awaitable behavior because the returned object is no longer a Promise. Nuxt’s documentation and community discussions recommend not wrapping or extending the returned object from useFetch
if you want to preserve its thenable nature [Nuxt useFetch API docs].
If you need to fetch both organization and events together, you can do so at the page level using Promise.all
or similar, but keep the composables themselves focused.
3. Anti-patterns to Avoid
- Don’t combine unrelated fetches in a single composable just for convenience. This can make your code harder to maintain and test.
- Don’t await inside a custom composable that wraps useFetch
or useAsyncData
—this can cause unexpected behavior, as noted in the Nuxt docs [Custom useFetch recipe].
4. If You Need to Fetch Both Together
If you have a use case where you always need both organization and events together, you can create a higher-level composable or utility that fetches both, but it should do so by calling the two focused composables internally:
But for most cases, keeping them separate is preferred.
---
Summary:- Use separate composables for organization and events. - Don’t spread/extend the result of
useFetch
if you want to keep thenable/awaitable behavior.
- Compose at the usage level (page/component) if you need both datasets together.
- This approach is in line with Nuxt’s best practices and will keep your codebase clean and maintainable [Nuxt useFetch API docs].
If you need more advanced patterns (like custom fetchers or repository patterns), Nuxt supports those as well, but the above is the recommended starting point [Custom useFetch recipe].
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@1235988804653940826> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai Would your recommendation change if both Organization and Event data came from the same API? I updated my original post to remove the part about separate APIs.
Let me check the knowledge base for you again. One moment! :books:
----------------------
If both Organization and Event data come from the same API, the core recommendation remains the same: separate composables for each resource are still the best practice in Nuxt. This approach keeps your code modular, reusable, and easier to maintain. The fact that both resources are fetched from the same API does not change the composable structure recommended by Nuxt documentation.
You can still have:
And use them together in your page or component:
This pattern is explicitly supported and encouraged in the Nuxt documentation, which emphasizes keeping composables focused and using them together as needed in your components or pages. There is no indication in the official docs that combining them into a single composable is preferred, even if the API endpoint is the same. In fact, the docs show examples of using multiple composables for related data, and recommend composing them at the usage level for clarity and maintainability [Nuxt useFetch API docs].
Summary:
- Keep composables focused on a single resource, regardless of whether they share an API. - Compose them together in your page/component as needed. - This approach is in line with Nuxt’s best practices and ensures maintainability and reusability. If you ever need to fetch both datasets in a single request for performance reasons, you can create a new composable for that specific use case, but for most scenarios, separate composables are preferred [Nuxt useFetch API docs]. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
- Keep composables focused on a single resource, regardless of whether they share an API. - Compose them together in your page/component as needed. - This approach is in line with Nuxt’s best practices and ensures maintainability and reusability. If you ever need to fetch both datasets in a single request for performance reasons, you can create a new composable for that specific use case, but for most scenarios, separate composables are preferred [Nuxt useFetch API docs]. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@1235988804653940826> Kapa.ai is still learning and improving, please let me know how I did by reacting below.