Home > Software engineering >  How to pass the data from page to default layout in nuxt 3
How to pass the data from page to default layout in nuxt 3

Time:01-04

I want to pass the data from page pages/index.vue to default layout layouts/default.vue. to set the dynamic breadcrumb according to the current page with the custom breadcrumb segment.

I have tried the vue 3 provide and inject option but not working and return always injection "foo" not found.. Please share ideas to archive this thing.

CodePudding user response:

You can use useState composable link. Which is provided by nuxt to share data across components. Or you can use a state management system like vuex or pinia

From nuxt.com useState is,

Nuxt provides useState composable to create a reactive and SSR-friendly shared state across components.

You can declare any variable with useState like this inside your pages directory

<script setup>
const counter = useState('counter', () => Math.round(Math.random() * 1000));
</script>

<template>
  <h1>Index page</h1>
  <div>
    <button @click="counter  ">Inc Counter From Index</button>
    <button @click="counter--">Dec Counter From Index</button>
  </div>
</template>

Then you can access that variable using useState from your layout like this

<script setup>
const counter = useState('counter');
</script>

<template>
  <div>
    Some default layout shared across all pages

    <h3>Counter value from the default layout = {{ counter }}</h3>
    <slot />
  </div>
</template>

Overall a minimal example are given in stackBliz here link

CodePudding user response:

I think the best way to share data between pages and layouts would be pinia.

https://pinia.vuejs.org/

https://pinia.vuejs.org/ssr/nuxt.html

You'll create a store (e.g. stores/breadcrumbs.ts):

import { defineStore } from "pinia";

export const useBreadcrumbsStore = defineStore('Breadcrumbs', () => {
    const title = ref('')
    // include any data you want
    return {
        title,
    }
})

then change the data in pages/index.vue

...
<script setup>
import { useBreadcrumbsStore } from '~/stores/breadcrumbs.ts'

const breadcrumbsStore = useBreadcrumbsStore()
// change the data
breadcrumbsStore.title = 'Some title'
</script>

and use it in your layouts/default.vue:

<template>
  <div>
    Title: {{ breadcrumbsStore.title }}<hr>
    <slot />
  </div>
</template>

<script setup>
import { useBreadcrumbsStore } from '~/stores/breadcrumbs.ts'
const breadcrumbsStore = useBreadcrumbsStore()
</script>

One thing to note here though - it will cause a Hydration text mismatch warning, so the title won't be rendered during SSR. You can get rid of the warning by wrapping it with ClientOnly tag like <ClientOnly>{{ breadcrumbsStore.title }}</ClientOnly>, but it won't solve the SSR issue.

  • Related