Search code examples
javascriptvue.jsvuejs2vue-componentvuex

How Can I change the value of a property in a component by a Vuex store action?


I've a Login view which contains a login form and a function which dispatches a Vuex store action called login. This action makes a POST request and I am wondering if I could change the error property found inside the Login view to something from inside the action dispatched in the Vuex store.

For example, inside this if:

if (response.status === 401) {
    console.log('Error logging in')
}

I would like to change the value of the error property to true. Is that possible?

<template lang="html">
    <div class="register">
        <div class="register-container">
            <p>Welcome back!</p>
            <form @submit.prevent="onSubmit" novalidate>
                <div class="margin-bottom-20">
                    <p>Email</p>
                    <input v-model='email' type='email'>
                </div>
                <div class="margin-bottom-20">
                    <p>Password</p>
                    <input v-model='password' type="password">
                </div>
                <div v-if='error'>Error</div>
                <button type="submit" name="button">Continue</button>
            </form>
        </div>
    </div>
</template>

<script>
import axios from 'axios'

export default {
    data(){
        return {
            email: '',
            password: '',
            error: false
        }
    },
    methods: {
        onSubmit(){
            let userInfo = {
                password: this.password,
                email: this.email
            }
            this.$store.dispatch('login', userInfo)
        }
    }
}
</script>

And this is the login action found in the Vuex store.

login({commit, dispatch}, userInfo){
    axios.post('/login', userInfo)
    .then(response => {
        if (response.status === 401) {
            console.log('Error logging in')
        } else {
            commit('authUser', {
                token: response.data.token,
                userId: response.data.userId,
                username: response.data.username
            })
            router.replace('/')
        }
    }).catch((error) => console.log(error));
},

Solution

  • The way i do it in my app is returning axios response object on the vuex action, and let the component check the response object

    For example:

    // I'm gonna use async-await syntax since it's cleaner
    async login({commit, dispatch}, userInfo){
        try {
            const response = await axios.post('/login', userInfo)
            if (response.status == 401) {
                commit('authUser', {
                    token: response.data.token,
                    userId: response.data.userId,
                    username: response.data.username
                })
                router.replace('/')
            }
            return response;
        } catch (err) {
            console.log(error)
        }
    },
    

    And on your component:

    methods: {
        async onSubmit(){
            let userInfo = {
                password: this.password,
                email: this.email
            }
            const response = await this.$store.dispatch('login', userInfo);
            if (response.status === 401) {
                this.error = true;
            } else {
                // This is optional since you already handling the router replace on the vuex actions
                // However i would put the replace on here instead of in vuex action since vuex actions should only contain logic for component state.
                this.$router.replace('/');
            }
        }
    }