Nuxt.js: asyncData and fetch is not working on TypeScript

Created on 22 Mar 2019  路  17Comments  路  Source: nuxt/nuxt.js

Version

v2.5.1

Reproduction link

https://codesandbox.io/s/13v2po80j4

Steps to reproduce

Update browser and please check the terminal

What is expected ?

Is output as 'asyncData' and 'fetch' on terminal

What is actually happening?

Not output

Additional comments?

I refferd to Official TypeScript support
Sorry for the poor English

This bug report is available on Nuxt community (#c8892)
bug-report

Most helpful comment

@Gomah @takenaka With nuxt-property-decorator you won't have any type checking and autocompletion on Nuxt methods.

asyncData & fetch should be in Component options.

@Component({
  asyncData (ctx) {
    ...
  }
})
export default class YourClass extends Vue {
...
}

instead of
```ts
@Component
export default class YourClass extends Vue {
asyncData (ctx) {
...
}
}

All 17 comments

It works fine with nuxt-property-decorator, maybe the typescript example should use the nuxt-property-decorator dependency instead? cc @kevinmarrec

With nuxt-property-decorator:
https://codesandbox.io/s/6l91r3qn5z

It's working!

Thank you so much 鈽猴笍

@Gomah @takenaka With nuxt-property-decorator you won't have any type checking and autocompletion on Nuxt methods.

asyncData & fetch should be in Component options.

@Component({
  asyncData (ctx) {
    ...
  }
})
export default class YourClass extends Vue {
...
}

instead of
```ts
@Component
export default class YourClass extends Vue {
asyncData (ctx) {
...
}
}

Hey @kevinmarrec ,

Just wondering how to properly use asyncData in the component decorator. I mean, it works, but not in this case:

@Component({
    asyncData(): Promise<{ entries: Entry<any>[] } | never> {
        return this.fetchExampleData().then((items) => {
            return { entries: items }
        })
    }
})

export default class Home extends Vue {
    entries: Entry<any>[] = [];

    fetchExampleData(): Promise<Entry<any>[] | never> {
        return contentfulClient.getEntries().then((entries) => {
            return entries.items
        })
    }
}

This gives: 32:21 Property 'fetchExampleData' does not exist on type 'Vue'. in the component decorator.

All the other lifecycle hooks that vue itself uses, like created() work fine on the class though, so I'd hope that would be possible for Nuxt in the future as well?

@FreekVR this has Vue type , so it works by default. If you need to use methods you defined in your Component class (which is extending Vue), you need to do :

asyncData(this: Home, ctx) to make it work :)
(You doesn't seem to need ctx so you can omit it)

@kevinmarrec thanks! That works for passing the typescript compiler :) But doesn't seem to work for the node server. "Cannot read property 'fetchExampleData' of undefined"

I'm thinking I might need to declare the class BEFORE the component decorator, but typescript doesn't allow me to use decorators after declaring a class :( Am I missing something here?

@FreekVR My bad, asyncData is called before initiating the component, you can't access to this here.
See the warning here : https://nuxtjs.org/api/

EDIT: You can directly use your contentfulClient in asyncData, right ?

Hey @kevinmarrec that works fine, but leads to a little bit of code duplication in some cases, but I guess in those cases (where both asyncCreated and some other actions do the same thing) we'd just need to declare that function in a const somewhere and use that :)

Thanks for the help!

@FreekVR Yep , for reusability, you can declare a const fetchData = () => { ... } at the top of the file or in a utils.ts file (or any name you want) if you planned to use it in other files :)

Do like this:

  @Component({
    async asyncData({ params, error }) {
     馃拃// impossible to use this.$http on @component 馃拃
      const http = Vue.prototype.$nuxt.$http;
      const payload1 = await http.get('/url')
      const payload2 = await http.post('/url', { params })

      return {
        data1: payload1.data,
        data2: payload2.data,
      }
    }
  })
  export default class NameOfYourClass extends Vue {
    name: 'NameOfYourClass'

    // AsyncData
    data1?: type
    data2?: type

    [...]
  }

I was wondering why the class-API example in the nuxt-typescript docs is using vue-property-decorator but not nuxt-property-decorator?

Hi all, try it like this

in your global.ts plugin

import { Component } from 'nuxt-property-decorator';
Component.registerHooks(['asyncData', 'head']);

Then in your component you can use it like this

export default class Component extends Vue {
  async asyncData({ route }) {
    ...
  }
  head(): MetaInfo {
    return {
      title: ...
    };
  }

}

I'm also having the same trouble to make asyncData work in a TypeScript setup. I'm using the latest Nuxt.js version 2.10.2 and followed all the setup instructions on https://typescript.nuxtjs.org/

Here is what I'm trying to do. I have a simple component ProductList which is the one which should make use of asyncData (at the moment only returning dummy data):

<template>
  <div>
    <h2>Product List</h2>
    <ul v-if="products">
      <li v-for="product in products" :key="product.id">{{ product.name }}</li>
    </ul>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'

@Component({
  async asyncData(ctx) {
    return {
      products: [
        { id: 1, name: 'Product A' },
        { id: 2, name: 'Product B' }
      ]
    }
  }
})
export default class ProductList extends Vue {
  products = []
}
</script>

This component is plugged into the main page of the project:

<template>
  <div>
    <h1>Nuxt.js Example</h1>
    <ProductList />
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import ProductList from '~/components/product-list.vue'

@Component({
  components: { ProductList }
})
export default class Homepage extends Vue {}
</script>

What I have configured in the project:

  • nuxt.config.ts contains buildModules: ['@nuxt/typescript-build'] as per documentation
  • tsconfig.json contains "experimentalDecorators": true

Current behaviour:

The asyncData function does not seem to be called at all. The dummy data returned never arrives in the ProductList component.

Expected behavior:

The asyncData function is called during the component rendering and the returned data overwrites the property values of the component.

Everything seems to compile and load without any errors. Am I still missing some settings?

@georgwittberger Simple, asyncData is triggered only for pages. Components don't have asyncData, you have to put your asyncData function in the HomePage page

@victorgarciaesgi Thank you so much for shedding light on this. I must have overlooked that important sentence in the docs: _asyncData is called every time before loading the page component._

Thanks for the quick response. 馃憤

No problem I had this problem too before! 馃槄

see https://github.com/nuxt-community/nuxt-class-component

Component decorator of 'vue-class-component'(also vue-property-decorators) will not detect nuxt specific hooks like 'asyncData' or 'head'.

All we need to do is to use Compnent decorator from 'nuxt-class-component'

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vadimsg picture vadimsg  路  3Comments

shyamchandranmec picture shyamchandranmec  路  3Comments

mattdharmon picture mattdharmon  路  3Comments

maicong picture maicong  路  3Comments

vadimsg picture vadimsg  路  3Comments