Nuxt 3 Architecture Question: Separating Logic from Components
Hi everyone 👋,
I’m in the process of refactoring my Nuxt 3 app and wanted to get some feedback on best practices. Right now, a lot of my components directly handle data fetching and business logic, but I’d like to move those responsibilities into composables for better testability and reusability.
The idea is to keep components as “dumb” UI pieces and move logic elsewhere. For example:
<!-- components/UserList.vue -->
// composables/useUsers.ts
This way I can test my data-fetching + derived state + helper functions in isolation without rendering the full component tree.
My questions for the community:
- Is moving fetching + business logic into composables a sound approach in Nuxt 3?
- Are there pitfalls I should be aware of (SSR concerns, test complexity, etc.)?
- Do you follow a different pattern for separating logic from UI?
Appreciate any insights or examples of how you structure this in larger Nuxt apps 🙏
3 Replies
Hi @jimbosupernova. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Your approach—moving data fetching and business logic into composables to keep components focused on UI—is a recommended and sound pattern in Nuxt 3. Here’s how this aligns with Nuxt’s best practices and some important considerations:
---
1. Is moving fetching + business logic into composables a sound approach in Nuxt 3?
Yes, this is a best practice in Nuxt 3.
Nuxt encourages the use of the composables/ directory for reusable logic, including data fetching, derived state, and helper functions. This pattern improves testability, reusability, and code organization. Your example of a
- Where you call composables matters:
Composables that use
When wrapping
- Composables are easier to test in isolation, but if they depend on Nuxt-specific APIs (like
- Use composables for logic, data fetching, and derived state. - Keep components focused on rendering and user interaction. - If you need to share logic between composables, you can nest composables or re-export them as needed [Nuxt composables directory usage]. --- Summary:
- Your approach is idiomatic and recommended in Nuxt 3. - Be careful to call composables using
Nuxt encourages the use of the composables/ directory for reusable logic, including data fetching, derived state, and helper functions. This pattern improves testability, reusability, and code organization. Your example of a
useUsers composable is directly in line with this guidance:
You can now use auto imported composable inNuxt composables directory usage --- 2. Are there pitfalls I should be aware of (SSR concerns, test complexity, etc.)? SSR Concerns:.js,.tsand.vuefiles
... Thecomposables/directory in Nuxt does not provide any additional reactivity capabilities to your code. Instead, any reactivity within composables is achieved using Vue's Composition API mechanisms, such as ref and reactive.
- Where you call composables matters:
Composables that use
useFetch or useAsyncData should be called directly in a setup function, plugin, or route middleware—not nested inside other composables or called outside of these contexts. Wrapping useFetch inside another function and calling it outside of setup can lead to bugs, especially with SSR and hydration, as data may be shared or overwritten between components unexpectedly [Stack Overflow: composable isolation issue].
- Key management:When wrapping
useAsyncData or useFetch in custom composables, always provide a unique key to avoid cache collisions and unexpected data sharing between components [Nuxt data fetching docs].
Test Complexity:- Composables are easier to test in isolation, but if they depend on Nuxt-specific APIs (like
useFetch), you may need to mock these in your tests.
---
3. Do you follow a different pattern for separating logic from UI?
Your pattern is the recommended one.- Use composables for logic, data fetching, and derived state. - Keep components focused on rendering and user interaction. - If you need to share logic between composables, you can nest composables or re-export them as needed [Nuxt composables directory usage]. --- Summary:
- Your approach is idiomatic and recommended in Nuxt 3. - Be careful to call composables using
useFetch/useAsyncData only in setup/plugin/middleware contexts.
- Always provide unique keys when wrapping data-fetching composables.
- This pattern scales well for larger apps and improves maintainability and testability.
If you want to see more examples or details, check the Nuxt composables documentation and data fetching guide.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@133227504566534144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Thank you for the advice kapa 🙏