Layouts & Data Patterns — Series 2

Preview — 3 of 10 questions

Why does binding :name on <NuxtLayout> (instead of setting a fixed layout in definePageMeta) allow the layout to change based on runtime state, like the user's auth status?

javascript
<!-- app.vue -->
<script setup>
const { loggedIn } = useAuth()
const layoutName = computed(() => (loggedIn.value ? 'dashboard' : 'guest'))
</script>

<template>
  <NuxtLayout :name="layoutName">
    <NuxtPage />
  </NuxtLayout>
</template>
A<NuxtLayout :name="..."> accepts a reactive value for which layout to render — since layoutName is a computed, <NuxtLayout> re-evaluates and swaps to the matching layout file whenever the underlying reactive source (loggedIn) changes, without needing a full page navigation; definePageMeta({ layout: 'dashboard' }), by contrast, is a static, compile-time value fixed per page and can't react to runtime state changes the same way
B:name and a static layout value in definePageMeta behave identically — both are re-evaluated reactively on every render
C<NuxtLayout :name="..."> can only be used inside app.vue — it has no effect if used anywhere else in the app
DBinding :name disables definePageMeta({ layout }) entirely for every page in the app, forcing all layout selection through this one binding

What does adding lazy: true (or using useLazyFetch directly) change about when navigation to a page completes?

javascript
<script setup>
const { data, pending } = await useFetch('/api/slow-report')
// vs.
const { data, pending } = useLazyFetch('/api/slow-report')
</script>
AuseLazyFetch skips the network request during SSR entirely, always fetching purely on the client after mount
BuseLazyFetch and await useFetch are functionally identical — the lazy naming is purely cosmetic
CPlain await useFetch(...) blocks navigation to the page until the fetch resolves — the router waits for the awaited promise before completing the route transition (and, during SSR, before the page can be sent to the client); useLazyFetch (or { lazy: true }) does not await the fetch before navigation completes — the page renders immediately with pending set to true, and the template is responsible for showing its own loading state until data arrives
DuseLazyFetch runs the request twice — once during SSR and once again after hydration, to guarantee freshness

Two unrelated pages both call useAsyncData('user', () => $fetch('/api/me')) and useAsyncData('user', () => $fetch('/api/user-preferences')) respectively. What actually goes wrong here?

javascript
// pages/profile.vue
const { data: user } = await useAsyncData('user', () => $fetch('/api/me'))

// pages/settings.vue
const { data: prefs } = await useAsyncData('user', () => $fetch('/api/user-preferences'))
ANothing goes wrong — the key 'user' is automatically scoped per-page/per-component, so these two calls never interfere with each other
BuseAsyncData throws a build-time error if the same key string is used in more than one file anywhere in the project
CNuxt uses the key ('user' in both cases) as the cache/dedup identifier for the fetched data — since both calls share the exact same key, Nuxt can treat them as the same logical request, potentially serving cached data from one call to the other (returning the wrong payload) or triggering unnecessary re-fetches when navigating between the two pages; keys need to be unique per distinct data source, not just descriptive
DThe second useAsyncData call silently overwrites the handler function of the first, permanently, for the rest of the app's lifetime

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.