鄭元傑
鄭元傑

Reputation: 1647

when to initialize vue and vuex state

Recently I design web that user was separated into "user"/"admin" two roles to login.
Different role would login same page but see the different buttons and functions.

MainPage.vue is the container so I call ajax "/init" to get user info and then commit to Vuex store.
Then Content.vue is the child page inside MainPage.vue. It would show different buttons by $store.state.user message.

However, I would like to call different api in mounted stage inside Content.vue according to user's role.
But the role would not be prepared which is commited by ajax called "/init" at this stage.

The overall flow is
// MainContent.vue

beforeCreate: async function () {
            await axios.post('/init').then(response => {
                if(response && response.data && response.data.data){
                    this.$store.commit("login", response.data.data)   
                }
            })
        }

// Content.vue

mounted: async function() {
    try {
      console.log(this.$store, this.$store.state.user, this.$store.getters.isAdmin)
      // no value here 
}

I have check the vue component lifecycle and saw beforeCreate of parent would be called before mounted of child.
Would lifecycle methods call in order even they are async function?
How should I solve this problem?

Thanks

Upvotes: 4

Views: 7357

Answers (2)

user320487
user320487

Reputation:

Your component lifecycle will not be a dependable way to handle this case since you're using an async call to fetch the user data. I would suggest displaying a loading state overlay and using mapGetters to access the store. This will provide a reactive mechanism for you to know when the user data is available. Below is a general idea for a single file component:

computed: {
    ...mapGetters({
        getLoggedInUser: 'GET_LOGGED_IN_USER',
        getIsUserAdmin: 'GET_IS_USER_ADMIN',
    })
}

....

<template>
    <content-overlay v-if="!getLoggedInUser">
         Loading...
    </content-overlay>

    ....
    <button v-if="getIsUserAdmin">Admin Button</button>
    <button v-if="!getIsUserAdmin">Regular User Button</button>

</template>

Upvotes: 1

user9246109
user9246109

Reputation:

You could delay the initialization of the Content component until the user state becomes available in Vuex by attaching a v-if directive to the Content component. Just make sure to initialize user with null in the Vuex state.

<!-- MainPage.vue -->
<template>
  <Content v-if="$store.state.user" />
</template>

Now this.$store.state.user and everything that depend on it should be available from Content component's mounted lifecycle hook.

Upvotes: 4

Related Questions