最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Calling a component function from the store once an action is complete in Vuex - Stack Overflow

programmeradmin7浏览0评论

I am trying to automatically scroll to the bottom of a div that contains a list of elements once a new element has been added.

Since adding and removing elements is done via Axios using an API, I have to wait for a response from the server in order to update my state in Vuex.

This means that, once an element is added in my state, every time I call the "scrollDown" function, the function scrolls to the second last element (due to the asynchronous Axios call not being registered yet).

My question is, how do I wait for the action in Vuex to finish and then call the function in my ponent to scroll to the bottom of my div?

I tried using watchers, puted properties, sending props, tracking changes from the actual state in Vuex and none of that worked...

// 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: ({ mit }, insertion) => {
    axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        mit('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 ponent 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;
  }
},

Any help is appreciated!

I am trying to automatically scroll to the bottom of a div that contains a list of elements once a new element has been added.

Since adding and removing elements is done via Axios using an API, I have to wait for a response from the server in order to update my state in Vuex.

This means that, once an element is added in my state, every time I call the "scrollDown" function, the function scrolls to the second last element (due to the asynchronous Axios call not being registered yet).

My question is, how do I wait for the action in Vuex to finish and then call the function in my ponent to scroll to the bottom of my div?

I tried using watchers, puted properties, sending props, tracking changes from the actual state in Vuex and none of that worked...

// 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: ({ mit }, insertion) => {
    axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        mit('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 ponent 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;
  }
},

Any help is appreciated!

Share Improve this question asked Mar 29, 2019 at 14:05 user7654617user7654617
Add a ment  | 

2 Answers 2

Reset to default 4

In vuex dispatched action returns a Promise. In case of your code its empty Promise, because there is nothing to return. You need to return/pass your axios Promise and then wait for it in your ponent. Look at this fixed code:

// 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: ({ mit }, insertion) => {
    return axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        mit('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 ponent 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;
  }
},

You could try using the async/await syntax.

This means when it will wait until this.$store.dispatch("addVisitor", insertion) is resolved, that means until response from the API is there, the next lines of code will not be executed.

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

Edit: And in your Vueux action, make sure to add a return statement.

const actions = {
  addVisitor: ({ mit }, insertion) => {
    return axios
      .post(state.url + 'api/visitor', {
        name: insertion.visitorName
      })
      .then(response => {
        mit('ADD_VISITOR', response);
      })
      .catch(error => state.errors.push(error.response.data.message));
    state.errors = [];
  },
}
发布评论

评论列表(0)

  1. 暂无评论