2
votes

Vue.js Objet dans le tableau non défini dans les données du magasin

Désolé si cela est vraiment évident, mais je suis nouveau dans Vue et je pourrais avoir besoin d'aide.

J'attrape un tableau de données (messages) de mon magasin et j'essaye de consigner un seul des objets du tableau, mais il est affiché indéfini à chaque fois. Si je console tout le tableau, il renvoie très bien.

Je suppose que c'est quelque chose à voir avec les données qui ne se chargent pas avant le console.log dans le hook créé? J'ai essayé tout ce que je pouvais et ça me rend dingue. Toute aide appréciée (code simplifié ci-dessous).

<script>
        export default {
          components: {},

     computed: {
            posts() {
              return this.$store.state.posts;
            }
          },
          created() {
            this.$store.dispatch("getPosts");
           console.log(this.posts[0])
           },
        };
        </script>


//Store code Below

export const state = () => ({
      posts: [],
    })

    export const mutations = {
      updatePosts: (state, posts) => {
        state.posts = posts
      }
    }

    export const actions = {
      async getPosts({
        state,
        commit,
        dispatch
      }) {
        if (state.posts.length) return

        try {
          let posts = await fetch(
            `${siteURL}/wp-json/wp/v2/video`
          ).then(res => res.json())

          posts = posts
            .filter(el => el.status === "publish")
            .map(({
              acf,
              id,
              slug,
              video_embed,
              title,
              date,
              content
            }) => ({
              acf,
              id,
              slug,
              video_embed,
              title,
              date,
              content
            }))

          commit("updatePosts", posts)
        } catch (err) {
          console.log(err)
        }
      }
    }


0 commentaires

4 Réponses :


3
votes

vous obtenez un indéfini car les fonctions asynchrones n'ont pas encore rempli l'état. Avec des données asynchrones, vous devez toujours utiliser des getters.

Le résultat de getter est mis en cache en fonction de ses dépendances et ne réévaluera que lorsque certaines de ses dépendances auront changé.

Vuex Getters

// component
computed: {
    posts() {
        return this.$store.getters['get_posts'];
    }
};

-

// Store
export const getters = {
    get_posts(state) {
        return state.posts;
    }
}


0 commentaires

3
votes

Comportement de la console expliqué

Lorsque vous enregistrez un objet ou un tableau dans la console, puis cliquez pour développer / afficher les propriétés, la console vous montre les propriétés telles qu'elles sont maintenant , au moment du clic, et non au moment du journal. Donc, s'ils ont changé après la journalisation, vous verrez les nouvelles valeurs.

Comment? Les objets et les tableaux étant des variables de référence, la console stocke la référence, puis se met à jour lorsque vous cliquez sur. Cela n'est vrai que pour les objets et les tableaux.

Inversement, lorsque vous connectez une primitive à la console, vous ne la voyez que telle qu'elle était au moment du journal.

Dans Chrome, vous verrez également un petit carré bleu à côté de l'objet dans la console. Lorsque vous passez la souris dessus, il vous indique: "La valeur ci-dessous a été évaluée à l'instant."


C'est pourquoi vous n'avez jamais vu la valeur lors de l'enregistrement d'un élément, car il s'agissait d'un élément qui n'existait pas encore. Mais les posts toujours une référence, car elles sont initialisées à un tableau vide. Ainsi, lors de l'enregistrement de la référence des posts , au moment où vous cliquez, les données sont arrivées.

Voici une démo qui essaie de rendre cela très clair.


1 commentaires

Je vous en prie. Aussi, méfiez - vous l'anti-modèle d'essayer d'accéder aux données fraîchement chargées dans created par une promesse d'action Vuex ( await ou .then ). Ce n'est pas considéré comme une bonne pratique .



1
votes

Vous devez utiliser les promesses selon la documentation https://vuex.vuejs.org/guide/actions.html#composing-actions . Votre action ne retournait pas sa promesse d'obtenir des données, et vous n'attendiez pas que la promesse soit résolue avant de consigner le résultat. Les promesses sont un concept très important à maîtriser. Voici un exemple qui correspond essentiellement à votre code, bien que j'aie utilisé setTimeout au lieu d'un vrai appel de récupération.

<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@2.5.0/dist/vuex.js"></script>
<div id="app">
</div>
const store = new Vuex.Store({
  state: {
    posts: []
  },
  getters: {
    itemList: (state) => {
      return state.items;
    }
  },
  mutations: {
    updatePosts: (state, posts) => {
      state.posts = posts
    }
  },
  actions: (actions = {
    async getPosts({ state, commit, dispatch }) {
      if (state.posts.length) {
        return Promise.resolve();
      }

      try {
        return new Promise(resolve => setTimeout(() => {
          const posts = [{ id: 42 }];
          commit("updatePosts", posts);
          resolve();
        }, 1000));
        
      } catch (err) {
        console.log(err);
      }
    }
  })
});

const app = new Vue({
  el: "#app",

  computed: {
    posts() {
      return this.$store.state.posts;
    }
  },
  created() {
    this.$store.dispatch("getPosts").then(() => console.log(this.posts[0]));
  },
  store
});


0 commentaires

0
votes

Si vous souhaitez obtenir les données correctes sur le hook created (), l'action doit être exécutée avant d'afficher les données.

  1. Dans le hook created() , vous pouvez distribuer l'action de manière asynchrone.
async created() {
    this.$store.dispatch("getPosts").then(()=> {
        console.log(this.posts[0]);
    });
},
  1. Vous pouvez utiliser les promesses JavaScript.
async created() {
    await this.$store.dispatch("getPosts");
    console.log(this.posts[0])
},


0 commentaires