Search code examples
vue.jsaxiosvuex

VUEX: can't get a recent store value


I am using Vuex and Axios together. And after dispatching an action I need to get an error message from response. I don't understand why do I get the correct response only after the second call.

Here I dispatch then use a getter.

this.$store.dispatch('registerUser', this.user);

this.errorMessage = this.getError;
console.log(this.errorMessage);

Getter is called in computed like this

  ...mapGetters({getError:"getErrorMsg"}),

The action with API call via Axios

 registerUser({commit}, user) {
        const form = new URLSearchParams();
        form.append('login', user.login);
        form.append('password', user.password);
        form.append('email', user.email);
        form.append('firstName', user.firstName);
        form.append('lastName', user.lastName);
        form.append('roles', user.roles);

        Axios.post(userUrl + '/create', form, config)
            .then(
                (response) => {
                    commit('setUser', response.data);
                    if (response.status === 206) {
                        commit('setErrorMessage', response.data);
                    }
                },
                (error) => {
                    commit('setErrorMessage', error.response.data);
                });

    }

So, how to get a correct message after making a call?


Solution

  • You are performing an AJAX request in your registerUser action, therefore it is an asynchronous operation. The setErrorMessage mutation is performed at some point in the future once the request has responded which happens after you access the this.getError getter.

    You need to wait for the registerUser to finish to allow for the error message to be set before you continue.

    I would read up on asynchronous JavaScript concepts like Promises, async/await, etc.

    You can fix this by making the following changes. First you need to return the promise returned by Axios.post():

    registerUser({commit}, user) {
      // code omitted
    
      return Axios.post(userUrl + '/create', form, config)
        .then(...)
    }
    

    Now when you dispatch the action, you need to wait for the promise to settle:

    this.$store.dispatch('registerUser', this.user)
      .finally(() => {
        this.errorMessage = this.getError;
        console.log(this.errorMessage);
      });
    

    Depending on browser support, instead of finally you may want to use then.