Closed jacquesmatthieu closed 4 years ago
Hey man! At first sight, serverPrefetch must return promise
So I must use an async / await
?
getExamAcademies() {
return Promise.all(
[this.$store.dispatch('currentExam', { examSlug: this.examSlug }),
this.$store.dispatch('getExamAcademies', {
examSlug: this.examSlug
})])
},
Please try something like this
<!-- Item.vue -->
<template>
<div v-if="item">{{ item.title }}</div>
<div v-else>...</div>
</template>
<script>
export default {
computed: {
// display the item from store state.
item () {
return this.$store.state.items[this.$route.params.id]
}
},
// Server-side only
// This will be called by the server renderer automatically
serverPrefetch () {
// return the Promise from the action
// so that the component waits before rendering
return this.fetchItem()
},
// Client-side only
mounted () {
// If we didn't already do it on the server
// we fetch the item (will first show the loading text)
if (!this.item) {
this.fetchItem()
}
},
methods: {
fetchItem () {
// return the Promise from the action
return this.$store.dispatch('fetchItem', this.$route.params.id)
}
}
}
</script>
So, you should return this.$store.dispatch
in your action, or if you have multiple dispatch functions return it in Promise all. I think it should work
It doesn't work ... I don't know why, Have you got vscode to share my IDE please ? :D
I'll try to check it for few next hours. Maybe do you have any repo to make reproducing easier?
Seems, this problem is unrelated to component. I tried to reproduce it and it works! Have a look:
<template>
<div>
{{ currentExam }}
<br>
{{ examAcademies }}
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'exnExamPage',
components: {},
metaInfo() {
return {
title: '',
meta: [
{
vmid: 'description',
name: 'description',
},
{
property: 'og:title',
},
{
property: 'og:description',
},
{
property: 'og:locale',
content: 'fr_FR',
},
{
property: 'og:url',
},
{
property: 'og:type',
content: 'article',
},
{
property: 'og:image',
content:
'https://storage.googleapis.com/prod-phoenix-bucket/exn/img_pages_exams.jpg',
},
{
property: 'og:image:width',
content: '590',
},
{
property: 'og:image:height',
content: '_',
},
],
link: [
{
rel: 'canonical',
},
],
};
},
props: {
currentYear: {
type: String,
default: '',
},
examSlug: {
type: String,
required: true,
},
},
data: () => ({
blocksSlug: [
'coaching_revisions',
'date_resultat_quand_1',
'date_resultat_quand_2',
'date_examen_epreuve_1',
'date_examen_epreuve_2',
'parcoursup_1',
'parcoursup_2',
'parcoursup_3',
'que_faire_apres_bts_1',
'que_faire_apres_bts_2',
'que_faire_apres_bts_3',
'que_faire_apres_recherche_emploi_1',
'que_faire_apres_recherche_emploi_2',
],
pending: true,
$t: () => {},
}),
computed: {
...mapGetters({
examAcademies: 'examAcademies',
currentExam: 'currentExam',
}),
hasOneExamAcademyPublished: function hasOneExamAcademyPublished() {
return this.examAcademies.some(element => {
return element.available;
});
},
},
serverPrefetch() {
return this.getExamAcademies();
},
mounted() {
if (!this.currentExam) {
this.getExamAcademies();
}
this.$store.watch(
(state, getters) => getters.examAcademies,
// eslint-disable-next-line no-unused-vars
(newValue, oldValue) => {
if (newValue.length > 0) {
this.pending = false;
}
},
);
},
methods: {
getExamAcademies() {
this.$store.dispatch('currentExam', { examSlug: 'Current exam' });
this.$store.dispatch('getExamAcademies', {
examSlug: 'Exam Academies',
});
},
},
};
</script>
And store module:
import axios from 'axios';
import {
MAIN__ITEM_DELELE,
MAIN__ITEM_ADD,
MAIN__ITEM_ADD_ASYNC,
MAIN__GET_DATA,
MAIN__SET_DATA,
} from '../const/main';
export default {
namespaced: false,
state: {
items: [
{
id: 1,
title: 'Milk',
},
{
id: 2,
title: 'Strawberry',
},
{
id: 3,
title: 'Egg',
},
],
dataFromApi: [],
currentExam: null,
},
mutations: {
[MAIN__ITEM_DELELE](state, { id }) {
state.items = state.items.filter(item => item.id !== id);
},
[MAIN__ITEM_ADD](state, { item }) {
const items = [...state.items];
items.push(item);
state.items = items;
},
[MAIN__SET_DATA](state, { data }) {
state.dataFromApi = data;
},
currentExam(state, { examSlug }) {
state.currentExam = examSlug;
},
examAcademies(state, { examSlug }) {
state.examAcademies = examSlug;
},
},
getters: {
currentExam(state) {
return state.currentExam;
},
examAcademies(state) {
return state.examAcademies;
},
},
actions: {
[MAIN__ITEM_ADD_ASYNC]({ commit }, { item }) {
setTimeout(() => {
commit(MAIN__ITEM_ADD, { item });
}, 1000);
},
async [MAIN__GET_DATA]({ commit }) {
try {
const resp = await axios.get(
'https://jsonplaceholder.typicode.com/posts',
);
commit(MAIN__SET_DATA, { data: resp.data });
} catch (e) {
console.error('Error fetching data');
}
},
async currentExam({ commit }, { examSlug }) {
commit('currentExam', { examSlug });
},
async getExamAcademies({ commit }, { examSlug }) {
commit('examAcademies', { examSlug });
},
},
};
Probably the problem with your store?
I solved it the problem with a simple return ;) Thanks dude.
Other things, how can I display a pageError with status code 404, currently I've got a 200
So, you could add error logic to entry-server.js You should caught errors there and render error page. Maybe I'll add this in future
Hi dude, I've used your boiterplate but I've got a probleme with
serverPrefetch()
.I have an API that returns data to me.
I launch this call via a dispatch in
serverPrefetch()
to fill my store but when I want to use the getters this one is undefined, you would know why?