Vue. js Объект в массиве не определен в данных из хранилища - PullRequest
1 голос
/ 03 апреля 2020

Извините, если это действительно очевидно, но я новичок в Vue и могу использовать некоторую помощь.

Я собираю массив данных (сообщений) из своего магазина и пытаюсь просто сохранить консольный журнал один из объектов в массиве, но он показывает неопределенный каждый раз. Если я консольный журнал весь массив, он возвращает нормально.

Я предполагаю, что это как-то связано с данными, которые не загружаются до console.log в созданном хуке? Я перепробовал все, что мог, и это сводило меня с ума. Любая помощь приветствуется (упрощенный код ниже).

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

Ответы [ 4 ]

3 голосов
/ 03 апреля 2020

вы получаете неопределенное значение, потому что асинхронные функции еще не заполнили состояние. С асинхронными данными вы всегда должны использовать геттеры.

Результат геттера кэшируется на основе его зависимостей и будет переоцениваться только при изменении некоторых его зависимостей.

Vuex Getters

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

-

// component
computed: {
    posts() {
        return this.$store.getters['get_posts'];
    }
};
2 голосов
/ 03 апреля 2020

Объяснение поведения консоли

Когда вы регистрируете существующий объект или массив на консоли, а затем нажимаете, чтобы развернуть / просмотреть свойства, консоль покажет вам свойства такими, какие они есть на момент щелкните , а не время журнала.

И наоборот, когда вы записываете примитив на консоль, вы видите его только таким, каким он был во время журнала.

Это Вот почему вы никогда не видели значение при регистрации одного элемента, потому что это был элемент, который еще не существовал. Но posts всегда имеет ссылку, так как он инициализирован в пустой массив. Поэтому, когда вы регистрируете ссылку posts, к тому времени, когда вы нажимаете, данные поступают.

Вот демо , которое пытается сделать это очень ясным.

1 голос
/ 03 апреля 2020

Вам нужно использовать обещания согласно документам https://vuex.vuejs.org/guide/actions.html#composing -action . Ваше действие не возвращало обещание получить данные, и вы не ожидали, что обещание будет выполнено, прежде чем консоль заблокировала результат. Обещания являются очень важной концепцией для освоения. Вот пример, который в основном соответствует вашему коду, хотя я использовал setTimeout вместо реального вызова извлечения.

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
});
<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>
0 голосов
/ 03 апреля 2020

Если вы хотите получить правильные данные на крюке созданного (), действие должно быть выполнено перед отображением данных.

  1. В хуке created() вы можете отправить действие асинхронно.
async created() {
    await this.$store.dispatch("getPosts");
    console.log(this.posts[0])
},
Вы можете использовать JavaScript Обещания.
async created() {
    this.$store.dispatch("getPosts").then(()=> {
        console.log(this.posts[0]);
    });
},
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...