major697
major697

Reputation: 1862

Vuex return null in Ajax query (first send)

I send email and password to Vuex:

this.$store.dispatch('login', {
    email: this.email,
    password: this.password
}).then(console.log(this.$store.state.login));

In Vuex I use Axios, this code is on actions:

    login(context, payload) {
        return new Promise((resolve, reject) => {
            let options = {
                method: "post",
                data: payload,
                url: "/api/login"
            };
            axios(options)
                .then(response => {
                    context.commit("login", response.data);
                    resolve();
                })
        });
    },

next I send data to the mutations:

login(state, login){
    state.login = login;
},

And to the state:

login: null

This is form:

<form method="post" @submit.prevent="sendLogin">
    <input type="email" id="email" name="email" v-model="email">
    <input type="password" id="password" name="password" v-model="password">
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

When I write email and password and click FIRST time Submit .then(console.log(this.$store.state.login)); return NULL, but when I second click Submit log return correctly data.

How I can resolve this ?

Upvotes: 0

Views: 24

Answers (1)

skirtle
skirtle

Reputation: 29122

Let's start here:

}).then(console.log(this.$store.state.login));

This is calling console.log immediately and passing its return value, undefined, to then. It's equivalent to writing this:

const loginPromise = this.$store.dispatch('login', {
    email: this.email,
    password: this.password
});

const x = console.log(this.$store.state.login);

loginPromise.then(x);

So at the point the logging occurs the asynchronous login will not have completed and the value logged will be null.

What you need is to wrap your logging in a function:

this.$store.dispatch('login', {
    email: this.email,
    password: this.password
}).then(() => {
    console.log(this.$store.state.login);
});

That should be sufficient but I would also note that the way you're creating a new Promise is likely unnecessary in your store. It should be possible to write it as this instead:

login(context, payload) {
    const options = {
        method: "post",
        data: payload,
        url: "/api/login"
    };

    return axios(options)
        .then(response => {
            context.commit("login", response.data);
        });
    },

So this will just return the promise that's returned by the then call.

You should rarely need to use the constructor to create a new promise. There are legitimate use cases but in cases where you already have a promise you should generally use some form of then chaining instead. See What is the explicit promise construction antipattern and how do I avoid it?

Upvotes: 1

Related Questions