0
votes

So, I attempting to update some data from component every time the state in vuex not null. I set up an API routes with laravel that returns user information after they logged in.

API routes:

Route::group(['middleware' => ['auth:api']], function () {
    Route::get('profil', 'Api\UserController@profil')->name('profile'); // will returning user info
}

Vuex:

export default new Vuex.Store({
    state: {
        token: localStorage.getItem('token') || "",
        user: {}
    },
    getters: {
        isAuth: state => {
            return state.token != "" && state.token != null
        }
    },
    mutations: {
        SET_TOKEN(state, payload) {
            state.token = payload
        },
        SET_AUTH_USER(state, payload) {
            state.user = payload
        }
    }
})

So in my App.vue, in created method, I commit SET_AUTH_USER with the http response as the payload if the token was exist.

App.vue:

<template>
  <div id="app-layout">
    <section-advices></section-advices>
</template>

<script>
    import SectionAdvices from "./SectionAdvices"


    export default {
        name: "app-layout",
        components: {
            SectionAdvices
        },
        created() {
            if (this.$store.state.token !== (null || "")) { //check token in vuex state
                this.$http
                    .get("/profil")
                    .then(res => {
                        if (res.status === 200) {
                            this.$store.commit("SET_AUTH_USER", res.data.data); //set $store.state.user with response
                        } else {
                            this.$store.commit("SET_AUTH_USER", null); // set with null
                        }
                     })
                     .catch(err => {
                         console.log(err);
                     });
            }
        }
    }
</script>

so far, everything works fine. every time I refresh the page, as long as there's a token in my local storage, the user object will always have the user information.

SectionAdvices.vue:

<template>
    <section class="advices">
        <input type="text" v-model="name">
        <input type="text" v-model="email">
    </section>
</template>

<script>
    import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
        export default {
            name: "section-advices",
            data(){
                return{
                    name: null,
                    email: null
                }
            },
            computed:{
                ...mapState(["user"]),
                ...mapGetters(["isAuth"]),
            },
            created() {
                if(this.isAuth) { //its returning true. the codes below was executed
                    this.name = this.user.name // gives name data with "undefined"
                    this.form.email = this.user.email // it's "undefined" too
                 }
             }
        }
</script>

Both name and email in SectionAdvices component was set as "undefined" although in Vue Dev tools, the user object does have these values. Did I call the api in App.vue inside wrong life cycle?

2
Probably your component is already loaded before your authentication method is finished, and why it passes isAuth is because token is undefined not "" and not null. - dreijntjens
yeah I think that too, and how i fixed it? I moved my auth process inside beforeCreate() but still no luck. still try to figure it out - Raden Kriting
Change the method in the store !!state.token and instead of created or beforeCreate watch isAuth and when it is true set the name and email - dreijntjens
alright i figured it out. you're absolutely correct by suggesting watcher. But the result still the same, its all undefined. checking isAuth (which returning boolean depends on token) to update my vuex state doesnt work, 1) I believe it's because my token saved in localStorage, which always fetched first before my api auth process. 2) my section advices component loaded before my auth api process is done. The solution, rather than watching my isAuth, I use watcher to my vuex user state to see any changes was made. Thank you! Can you answer my question so i can vote as the right answer? - Raden Kriting
!!state.store checks on not null, not undefined and not empty string. Alternatively you also can add the authentication in beforeRoute, and enter the route when the token is loaded - dreijntjens

2 Answers

0
votes

Can you try to use getters to take state data? Because of lifecycles. Getters are setting first when component page rendering

0
votes

I found th solution, which is:

as what @dreijntjens suggested, I added watcher in my "SectionAdvices.vue"

...
watch: {
    // watching for store.state.user changes
    user: {
        handler: "fillForm", // call the method
        immediate: true // this watcher will exec immediately after the comp. created
    }
 },
 methods: {
    fillForm() {
        if(this.isAuth) { // this is not necessary, just want to make sure. Once isAuth === true, codes below will be executed
            this.form.name = this.user.name
            this.form.email = this.user.email
        }
    }
 }

So, the real problem is, when SectionAdvices.vue created and fetching data, store.state.user still an empty object. My API calls runs after this step, which is pointless. So, it's true I need watcher, to see any changes in user state and update the local data inside its component after that.