Need help loading data

This is my first time using Nuxt (v3). Last time I used Vue on a sizeable project was in 2020, but I've been reading the news so I'm not totally lost. But I need help loading data from a backend server. I have read the Nuxt guide on loading data but I've still not figured out a solid pattern that works for all/most use cases. I'm currently using this pattern: https://medium.com/@luizzappa/nuxt-3-repository-pattern-organising-and-managing-your-calls-to-apis-with-typescript-acd563a4e046 It seems to be working well so far (although I still want some adjustments, example not repeating .data) except that this page crashes with 500 from Nuxt dev server Error: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'id') I know it's related to useRoute().prams.id because when I pass a string literal to getCases() method, it works. Is there guidance on the best way to approach this?
Medium
Nuxt 3 | Repository pattern: organising and managing your calls to ...
In Nuxt 2 the use of axios was straightforward and allowed a good management of API calls. When I started to develop with Nuxt 3 I found it…
3 Replies
kapa.ai
kapa.ai4d ago
Hi @the_aceix. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- You're correct that the error is related to how you're accessing the route parameter. In Nuxt 3, the recommended way to access dynamic route parameters is using the useRoute() composable. However, a common pitfall is that useRoute().params.id may be undefined on the initial render, especially if the route hasn't been fully resolved yet. Key points and solutions: 1. Always use the Nuxt useRoute composable
Make sure you're importing useRoute from Nuxt, not directly from vue-router, to avoid synchronization issues during navigation.
const route = useRoute()
const id = route.params.id

const route = useRoute()
const id = route.params.id

Nuxt useRoute composable 2. Handle undefined params gracefully
Route params can be undefined initially. You should guard against this, especially if you use them in API calls. For example:
const route = useRoute()
const id = computed(() => route.params.id)

const { data, error } = await useFetch(() => id.value ? `/api/cases/${id.value}` : null)

const route = useRoute()
const id = computed(() => route.params.id)

const { data, error } = await useFetch(() => id.value ? `/api/cases/${id.value}` : null)

This pattern ensures the fetch only runs when id is available.
Computed URL and reactivity 3. Use computed or watch for reactivity
If you want your data to refetch when the route param changes, use a computed getter for the URL or watch the param:
const route = useRoute()
const id = computed(() => route.params.id)

const { data, error } = await useFetch(() => id.value ? `/api/cases/${id.value}` : null)

const route = useRoute()
const id = computed(() => route.params.id)

const { data, error } = await useFetch(() => id.value ? `/api/cases/${id.value}` : null)

Reactive keys and shared state 4. Avoid destructuring params directly
Do not do const { id } = useRoute().params in the top-level of your setup, as this will not be reactive and may be undefined. Always use a computed or access route.params.id directly. Summary:
- Use const route = useRoute() and access route.params.id via a computed or directly. - Guard against undefined values before making API calls. - Use a computed getter for the fetch URL to ensure reactivity and avoid errors. This approach should resolve your 500 error and make your data fetching more robust in Nuxt 3. If you want to avoid repeating .data, consider wrapping your repository methods or using composables to abstract that logic, but always ensure you handle the possibility of undefined route params. For more details and examples, see the official Nuxt documentation on data fetching, useRoute, and computed URLs. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4d ago
<@448141117368827905> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
the_aceix
the_aceixOP4d ago
<script setup lang="ts">
// ...

const caseId = useRoute().params.id;
const { $api } = useNuxtApp();

const { data: caseData, status, refresh } = await $api.cases.getCase(caseId as string);

onBeforeMount(async () => {
if (typeof caseId !== "string") {
await navigateTo({ name: AppPages.Cases });
return;
}
});
</script>

<template>
<!-- -->
<Card class="shadow-none border-none">
<CardContent class="py-4">
<div class="flex justify-between">
<div class="">
<h2 class="text-2xl">{{ caseData?.data.name }}</h2>
<p class="text-sm text-muted-foreground">
Case Number: {{ caseData?.data.caseNumber }}
</p>
</div>
<div class="flex gap-2 items-end">
<Badge
variant="outline"
:dot-color="caseData?.data.stage.color"
>
{{ caseData?.data.stage.name }}
</Badge>
<CasesEditCaseModal v-if="caseData" :case="caseData.data">
<template #trigger>
<Button>Edit Case</Button>
</template>
</CasesEditCaseModal>
</div>
</div>
</CardContent>
</Card>
<!-- -->
</template>
<script setup lang="ts">
// ...

const caseId = useRoute().params.id;
const { $api } = useNuxtApp();

const { data: caseData, status, refresh } = await $api.cases.getCase(caseId as string);

onBeforeMount(async () => {
if (typeof caseId !== "string") {
await navigateTo({ name: AppPages.Cases });
return;
}
});
</script>

<template>
<!-- -->
<Card class="shadow-none border-none">
<CardContent class="py-4">
<div class="flex justify-between">
<div class="">
<h2 class="text-2xl">{{ caseData?.data.name }}</h2>
<p class="text-sm text-muted-foreground">
Case Number: {{ caseData?.data.caseNumber }}
</p>
</div>
<div class="flex gap-2 items-end">
<Badge
variant="outline"
:dot-color="caseData?.data.stage.color"
>
{{ caseData?.data.stage.name }}
</Badge>
<CasesEditCaseModal v-if="caseData" :case="caseData.data">
<template #trigger>
<Button>Edit Case</Button>
</template>
</CasesEditCaseModal>
</div>
</div>
</CardContent>
</Card>
<!-- -->
</template>

Did you find this page helpful?