Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asyncData and fetch is not working on TypeScript #5330

Closed
takenaka opened this issue Mar 22, 2019 · 23 comments
Closed

asyncData and fetch is not working on TypeScript #5330

takenaka opened this issue Mar 22, 2019 · 23 comments

Comments

@takenaka
Copy link

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)
@ghost ghost added the cmty:bug-report label Mar 22, 2019
@Gomah
Copy link
Sponsor

Gomah commented Mar 22, 2019

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

@takenaka
Copy link
Author

It's working!

Thank you so much ☺️

@kevinmarrec
Copy link
Contributor

kevinmarrec commented Mar 22, 2019

@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

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

@FreekVR
Copy link

FreekVR commented Mar 27, 2019

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?

@kevinmarrec
Copy link
Contributor

kevinmarrec commented Mar 27, 2019

@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)

@FreekVR
Copy link

FreekVR commented Mar 27, 2019

@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?

@kevinmarrec
Copy link
Contributor

kevinmarrec commented Mar 27, 2019

@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 ?

@FreekVR
Copy link

FreekVR commented Mar 27, 2019

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!

@kevinmarrec
Copy link
Contributor

kevinmarrec commented Mar 27, 2019

@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 :)

@joffreyBerrier
Copy link
Sponsor

joffreyBerrier commented Jun 5, 2019

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

    [...]
  }

@541xxx
Copy link

541xxx commented Oct 18, 2019

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

@victorgarciaesgi
Copy link

victorgarciaesgi commented Oct 30, 2019

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: ...
    };
  }

}

@georgwittberger
Copy link

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?

@victorgarciaesgi
Copy link

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

@georgwittberger
Copy link

@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. 👍

@victorgarciaesgi
Copy link

No problem I had this problem too before! 😅

@yoshiya0503
Copy link

yoshiya0503 commented Feb 15, 2020

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'

@shresthapradip
Copy link

shresthapradip commented Apr 13, 2021

Hi all,
I am using the following code and console log is always printing undefined. Any idea why? When I put breakpoint and try to find data with value, it is in globalThis['__NUXT__']['data'][0].

page path: /hello

  import {Component, Prop, Vue, Watch} from 'nuxt-property-decorator';
  import {Context} from '@nuxt/types';
  @Component({
    async asyncData(ctx: Context) {
      console.log("Server side asyncData")
      return {data: "Hello World"}
    }
  })

  export default class Hello extends Vue {
    data?: string;
    async mounted() {
      console.log(this.data) // Always printing undefined
    }
    .....

All outputs:

Server side asyncData
undefined

@georgwittberger
Copy link

@shresthapradip , I've just tried to reproduce the issue with the following (plain JavaScript) version and it worked fine.

import { Component, Vue } from "nuxt-property-decorator";

@Component({
  async asyncData(ctx) {
    console.log("asyncData called");
    return { data: "Hello World" };
  }
})
export default class TestPage extends Vue {
  data = null;
  async mounted() {
    console.log(this.data);
  }
}

I've tested both target: server and target: static in both development server and after production build using yarn build and yarn start. In all four scenarios the data "Hello World" was logged correctly inside the mounted hook.

My Nuxt version is 2.15.4. Could you try the latest version in your project? Otherwise, I assume more context info is needed to further analyze that issue.

@shresthapradip
Copy link

@shresthapradip , I've just tried to reproduce the issue with the following (plain JavaScript) version and it worked fine.

import { Component, Vue } from "nuxt-property-decorator";

@Component({
  async asyncData(ctx) {
    console.log("asyncData called");
    return { data: "Hello World" };
  }
})
export default class TestPage extends Vue {
  data = null;
  async mounted() {
    console.log(this.data);
  }
}

I've tested both target: server and target: static in both development server and after production build using yarn build and yarn start. In all four scenarios the data "Hello World" was logged correctly inside the mounted hook.

My Nuxt version is 2.15.4. Could you try the latest version in your project? Otherwise, I assume more context info is needed to further analyze that issue.

I am sorry. I had one @watch function which was causing this issue. Thank you for your guidance.

@fahmiegerton
Copy link

What about with Options API? Still got Property xxx does not exist on type

@Radiergummi
Copy link

is there any way to use asyncData return values without decorators?

@danielroe
Copy link
Member

@Radiergummi You might want to follow #9239.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests