-
-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Async data in nested component #32
Comments
Actually it is not possible because it's not linked to a route, Nuxt.js surcharges the component data() associated to a route to allow async data. For sub components, there are 2 ways of achieving it:
It all depends if you want the sub components to be server-rendered or not. I hope it solves your issue :) |
This is kind of what I feared. I've been reading Vue 2's documentation, it looks like Vuex becomes basically mandatory. Which also solves this problem. I guess the real clean solution is to use Vuex, right? |
Yes of course I forgot about vuex, you can integrate the store easily with Nuxt.js, just add a store/index.js (look at examples/vuex-store) |
@Xowap Can you provide an example how implement it? thanks 😄 |
An example would really help. |
@atinux Could you elaborate why this is not possible? All the components should be known beforehand statically and it should be possible to make the appropriate calls with the given context. I'm looking into how to solve the issue myself, too, as it would tremendously improve modularization. |
Hi @Etheryte Sadly, there is no way to know the component three inside But it's also a good thing to not call asyncData for "normal" components since it let's everyone create Vue component compatible with the same behaviour under nuxt.js and a basic vue app. |
Use this function. That will test all child component function fetchDeep(component){
var originFn =component.asyncData;
component.asyncData =async function (ctx) {
if(component.components){
let childComponents =Object.values(component.components);
console.log(childComponents);
while(childComponents.length){
let comp =childComponents.shift();
if(comp.options.fetch) await comp.options.fetch(ctx);
if(comp.components) childComponents.push(...Object.values(comp.components));
}
};
return originFn(ctx);
};
return component;
}; There is an example: A nav component. import Vue from "vue"
import {mapGetters} from "vuex"
import Component from 'nuxt-class-component';
@Component({
name :'blog-nav',
async fetch({store}){
await store.dispatch('fetchCategory');
},
computed :{
...mapGetters(['categoryMap']),
},
})
export default class extends Vue {
showCategory =['technology','works','think'];
} A page component which import nav component. import Vue from "vue"
import Component from 'nuxt-class-component';
import {ArticleInfo} from "@foxzilla/fireblog";
import Marked from 'marked';
import Nav from '~/components/blog-nav.vue';
import {fetchDeep} from '~/modules/jslib';
@Component(fetchDeep({ // ❗️❗️❗️
async asyncData(ctx){
var articleInfo:ArticleInfo =await ctx.app.$axios.$get(`/article/detail/${ctx.params.id}`);
await (<any>Nav).options.fetch(ctx);
return {articleInfo}
},
head(val:ArticleInfo){
return {
title: this.articleInfo.title,
};
},
components :{
'blog-nav' :Nav,
},
}))
export default class extends Vue {
articleInfo:ArticleInfo;
md:(mdContent:string)=>string =Marked;
} |
Use this function. That will test all child component export function fetchDeep(component){
var originFn =component.asyncData;
var fetchedComp =[];
component.asyncData =async function (ctx) {
if(component.components){
let childComponents =Object.values(component.components);
while(childComponents.length){
let comp =childComponents.shift();
if(fetchedComp.includes(comp))continue;
else fetchedComp.push(comp);
if(comp.options && comp.options.fetch) await comp.options.fetch(ctx);
if(comp.fetch) await comp.fetch(ctx);
if(comp.components) childComponents.push(...Object.values(comp.components));
if(comp.options && comp.options.components) childComponents.push(...Object.values(comp.options.components));
}
};
return originFn && originFn(ctx);
};
return component;
}; There is an example: A nav component. import Vue from "vue"
import {mapGetters} from "vuex"
import Component from 'nuxt-class-component';
@Component({
name :'blog-nav',
async fetch({store}){ // will be called
await store.dispatch('fetchCategory');// use vuex
},
computed :{
...mapGetters(['categoryMap']),
},
})
export default class extends Vue {
showCategory =['technology','works','think'];
} A page component which import nav component. import Vue from "vue"
import Component from 'nuxt-class-component';
import {ArticleInfo} from "@foxzilla/fireblog";
import Nav from '~/components/blog-nav.vue';
import {fetchDeep} from '~/modules/jslib';
@Component(fetchDeep({ // ❗️❗️❗️
async asyncData(ctx){
var articleInfo:ArticleInfo =await ctx.app.$axios.$get(`/article/detail/${ctx.params.id}`);
await (<any>Nav).options.fetch(ctx);
return {articleInfo}
},
components :{
'blog-nav' :Nav,
},
}))
export default class extends Vue {
} |
@pea3nut Does this work with SSR as well? I tried a similar approach a few releases ago and had a ton of problems getting it to work on the server side. |
@Etheryte It doesn't have a strong test, but now it works on Of course, my app is not complex enough now, maybe some bug hidden is there. |
I've updated your function with possibility to leave empty fetch or asyncData component property and also use both fetch or asyncData on chold components:
Is it correct that collecting all promises to resolve in array and then call Promise.all theoretically would work faster that couple of await? On it doesn't matter on server side render? And is it correct assumption that component promise resolve order is unimportant in such case? |
@Romick2005 I found some bugs in my export function fetchDeep(component){
var originFn =component.asyncData;
var fetchedComp =[];
component.asyncData =async function (ctx) {
if(component.components){
let childComponents =Object.values(component.components);
while(childComponents.length){
let comp =childComponents.shift();
if(fetchedComp.includes(comp))continue;
else fetchedComp.push(comp);
if(comp.options && comp.options.fetch) await comp.options.fetch(ctx);
if(comp.fetch) await comp.fetch(ctx);
if(comp.components) childComponents.push(...Object.values(comp.components));
if(comp.options && comp.options.components) childComponents.push(...Object.values(comp.options.components));
}
};
return originFn && originFn(ctx);
};
return component;
}; It's a little ugly... and too hackly. |
And, I'm no idea of how to use the async data in the component of |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Hi,
It seems that loading async data is pretty easy from pages, yet I don't find any way to load data asynchronously from nested components.
To explain what I try to do, I made some example project: https://github.com/Xowap/nuxttest
You'll see that data loaded from
index.vue
is correctly rendered server-side yet data inHttpBin.vue
isn't displayed at all and triggers an error.Is that an anti-pattern? A feature to come?
Thanks,
Rémy
The text was updated successfully, but these errors were encountered: