Вызов функции компонента из хранилища после завершения действия в Vuex - PullRequest
1 голос
/ 29 марта 2019

Я пытаюсь автоматически прокрутить до конца элемента div, который содержит список элементов, после добавления нового элемента.

Поскольку добавление и удаление элементов выполняется через Axios с использованием API, мне нужно дождаться ответа от сервера, чтобы обновить мое состояние в Vuex.

Это означает, что после добавления элемента в мое состояние каждый раз, когда я вызываю функцию "scrollDown", функция прокручивается до второго последнего элемента (из-за того, что асинхронный вызов Axios не был зарегистрирован пока).

У меня вопрос: как мне дождаться завершения действия в Vuex, а затем вызвать функцию в моем компоненте, чтобы прокрутить до конца моего div?

Я пытался использовать наблюдателей, вычисленные свойства, отправлять реквизиты, отслеживать изменения от фактического состояния в Vuex, но ничего из этого не помогло ...

// VUEX

const state = {
  visitors: [],
  url: 'API URL',
  errors: []
}
const mutations = {
  ADD_VISITOR(state, response) {
    const data = response.data;
    data.Photos = [];
    state.visitors.data.push(data);
  },
}
const actions = {
  addVisitor: ({ commit }, insertion) => {
    axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        commit('ADD_VISITOR', response);
      })
      .catch(error => state.errors.push(error.response.data.message));
    state.errors = [];
  },
}

// MY COMPONENT FROM WHERE THE ACTIONS ARE BEING DISPATCHED

<div ref="scroll" class="visitors-scroll">
  <ul v-if="visitors.data && visitors.data.length > 0" class="list-group visitors-panel">
    <!-- Displaying appVisitor component and sending data as a prop -->
    <app-visitor v-for="visitor in visitors.data" :key="visitor.id" :visitor="visitor"></app-visitor>
  </ul>
</div>

methods: {
  // Function that dispatches the "addVisitor" action to add a new visitor to the database
  newVisitor() {
    const insertion = {
      visitorName: this.name
    };
    if (insertion.visitorName.trim() == "") {
      this.errors.push("Enter a valid name!");
    } else {
      this.$store.dispatch("addVisitor", insertion);
      this.name = "";
    }
    this.errors = [];
    this.scrollDown(); // I WANT TO CALL THIS FUNCTION WHEN AXIOS CALL IS FINISHED AND MUTATION IN VUEX IS COMPLETED
  },
  scrollDown() {
    this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight;
  }
},

Любая помощь приветствуется!

Ответы [ 2 ]

1 голос
/ 29 марта 2019

В отправленном действии vuex возвращается Обещание.В случае вашего кода его пустое обещание, потому что возвращать нечего.Вам нужно вернуть / передать ваш Axios Promise, а затем дождаться его в вашем компоненте.Посмотрите на этот фиксированный код:

// VUEX

const state = {
  visitors: [],
  url: 'API URL',
  errors: []
}
const mutations = {
  ADD_VISITOR(state, response) {
    const data = response.data;
    data.Photos = [];
    state.visitors.data.push(data);
  },
}
const actions = {
  addVisitor: ({ commit }, insertion) => {
    return axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        commit('ADD_VISITOR', response);
      })
      .catch(error => state.errors.push(error.response.data.message));
    state.errors = [];
  },
}

// MY COMPONENT FROM WHERE THE ACTIONS ARE BEING DISPATCHED

<div ref="scroll" class="visitors-scroll">
  <ul v-if="visitors.data && visitors.data.length > 0" class="list-group visitors-panel">
    <!-- Displaying appVisitor component and sending data as a prop -->
    <app-visitor v-for="visitor in visitors.data" :key="visitor.id" :visitor="visitor"></app-visitor>
  </ul>
</div>

methods: {
  // Function that dispatches the "addVisitor" action to add a new visitor to the database
  newVisitor() {
    const insertion = {
      visitorName: this.name
    };
    if (insertion.visitorName.trim() == "") {
      this.errors.push("Enter a valid name!");
    } else {
      this.$store.dispatch("addVisitor", insertion)
        .then(() => {
           this.scrollDown();
         })
      this.name = "";
    }
    this.errors = [];
  },
  scrollDown() {
    this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight;
  }
},
1 голос
/ 29 марта 2019

Вы можете попробовать использовать синтаксис async/await.

Это означает, что когда он будет ожидать разрешения this.$store.dispatch("addVisitor", insertion), то есть до тех пор, пока не будет получен ответ от API, следующие строки кода не будут выполнены.

methods: {
  // Function that dispatches the "addVisitor" action to add a new visitor to the database
  async newVisitor() {
    const insertion = {
      visitorName: this.name
    };
    if (insertion.visitorName.trim() == "") {
      this.errors.push("Enter a valid name!");
    } else {
      await this.$store.dispatch("addVisitor", insertion);
      this.name = "";
    }
    this.errors = [];
    this.scrollDown();
  },
  scrollDown() {
    this.$refs.scroll.scrollTop = this.$refs.scroll.scrollHeight;
  }
}

Редактировать:И в вашем действии Vueux обязательно добавьте оператор return.

const actions = {
  addVisitor: ({ commit }, insertion) => {
    return axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        commit('ADD_VISITOR', response);
      })
      .catch(error => state.errors.push(error.response.data.message));
    state.errors = [];
  },
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...