'Nuxt.js cannot update head() properties from asyncData()
I created a server-side rendered Vue.js blog using Nuxt.js with Typescript and Ghost but I'm having some issues to update html metatag using data from asyncData().
From Nuxt.js documentation I know that asyncData() is called every time before loading page components and merges with component data.
I'm getting this error:
Property 'title' does not exist on type '{ asyncData({ app, params }: Context): Promise<{ title: string | undefined; excerpt: string | undefined; feature_image: Nullable | undefined; html: Nullable | undefined; }>; head(): any; }'.
This is my code:
<script lang="ts">
import { Context } from '@nuxt/types'
import { PostOrPage } from 'tryghost__content-api'
export default {
async asyncData ({ app, params }: Context) {
const post: PostOrPage = await app.$ghost.posts.read(
{
slug: params.slug
},
{ include: 'tags' }
)
return {
title: post.title,
excerpt: post.excerpt,
feature_image: post.feature_image,
html: post.html
}
},
head () {
return {
title: this.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.excerpt
}
]
}
}
}
</script>
I already tried some solutions like using data() to set a default value for each item but nothing. Do you have any suggestion?
Solution 1:[1]
Without a typescript plugin like nuxt-property-decorator you won't have Typescript support for nuxt (either way, type checking and autocomplete still won't work).
That's why asyncData & fetch should be in Component options.
@Component({
asyncData (ctx) {
...
}
})
export default class YourClass extends Vue {
...
}
instead of
@Component
export default class YourClass extends Vue {
asyncData (ctx) {
...
}
}
If you still want to use asyncData() inside of your component class instead of setting the option, see this working example using the npm module nuxt-property-decorator.
Solution 2:[2]
Here is the working code after implementing the suggestion from @nonNumericalFloat :
import { Component, Vue } from 'nuxt-property-decorator'
import { Context } from '@nuxt/types'
import { PostOrPage } from 'tryghost__content-api'
import Title from '~/components/Title.vue'
@Component({
components: {
Title
}
})
export default class Page extends Vue {
post!: PostOrPage
async asyncData ({ app, params }: Context) {
const post: PostOrPage = await app.$ghost.posts.read(
{
slug: params.slug
},
{ include: 'tags' }
)
return {
post
}
}
head () {
return {
title: this.post.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.post.excerpt
}
]
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | marco.santonocito |
