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/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.