[Vuejs]-Vuex action does not work properly in a vue mounted hook

1👍

First of all, it’s just a small detail, but you don’t need need to make your ‘getUserId’ action async, since it does not use the ‘await’ keyword. So can simplify this :

async getUserId() {
  const user = firebase.auth().currentUser;
  return user ? user.uid : null;
}

const userId = await dispatch('getUserId')

into this :

getUserId() {
  const user = firebase.auth().currentUser;
  return user ? user.uid : null;
}

const userId = dispatch('getUserId')

Coming back to your id that seems to be undefined, the problem here is that your ‘mounted’ event is probably triggered before the ‘login’ can be completed.

How to solve this case ? Actually, there are a lot of different ways to approch this. What I suggest in your case is to use a middleware (or a ‘route guard’). This guard can make you are verified user before accessing some routes (and eventually restrict the access or redirect depending on the user privileges). In this way, you can make sure that your user is defined before accessing the route.

This video is 4 years old so it is not up to date with the last versions of Firebas. But I suggest The Net Ninja tutorial about Vue Route Guards with Firebase if you want to learn more about this topic.

👤Dony

0👍

Accepted answer actually pointed me to the correct direction.
In my case i had to make a route guard for child routes.

router.vue

import Vue from 'vue'
import Router from 'vue-router'
import firebase from 'firebase/app';

Vue.use(Router);

const router = new Router({
  mode: 'history',
    routes: [
    {
      path: '/',
      name: 'home',
      meta: {layout: 'main-layout'},
      component: () => import('./views/main/Home.vue')
    },
    {
      path: '/bouquets',
      name: 'bouquets',
      meta: {layout: 'main-layout'},
      component: () => import('./views/main/Bouquets.vue')
    },
    {
      path: '/sets',
      name: 'sets',
      meta: {layout: 'main-layout'},
      component: () => import('./views/main/Sets.vue')
    },
    {
      path: '/cart',
      name: 'cart',
      meta: {layout: 'main-layout'},
      component: () => import('./views/main/Cart.vue')
    },
    {
      path: '/login',
      name: 'login',
      meta: {layout: 'empty-layout'},
      component: () => import('./views/empty/Login.vue')
    },
    {
      path: '/register',
      name: 'register',
      meta: {layout: 'empty-layout'},
      component: () => import('./views/empty/Register.vue')
    },
    {
      path: '/admin',
      name: 'admin',
      meta: {layout: 'admin-layout', auth: true},
      component: () => import('./views/admin/Home.vue'),
      children: [
        {
          path: 'categories',
          name: 'adminCategories',
          meta: {layout: 'admin-layout', auth: true},
          component: () => import('./views/admin/Categories'),
        },
        {
          path: 'subcategories',
          name: 'adminSubcategories',
          meta: {layout: 'admin-layout', auth: true},
          component: () => import('./views/admin/SubCategories'),
        },
        {
          path: 'products',
          name: 'adminProducts',
          meta: {layout: 'admin-layout', auth: true},
          component: () => import('./views/admin/Products'),
        },
      ]
    },
    {
      path: '/checkout',
      name: 'checkout',
      meta: {layout: 'main-layout'},
      component: () => import('./views/main/Checkout.vue')
    },
    {
      path: '/:subcategory',
      name: 'subcategory',
      meta: {layout: 'main-layout'},
      props: true,
      params: true,
      component: () => import('./views/main/Subcategory.vue')
    },
  ]
})

router.beforeEach((to, from, next) => {
  //if currentUser exists then user is logged in
  const currentUser = firebase.auth().currentUser;
  //does a route has auth == true
  const requireAuth = to.matched.some(record => record.meta.auth);
  //if auth is required but user is not authentificated than redirect to login
  if (requireAuth && !currentUser) {
    // next('/login?message=login');
    next('login')
  } else {
    next();
  }
})

export default router;

category.js fetchCategories() action

  async fetchCategories({commit, dispatch}) {
      const userId = await dispatch('getUserId')

      try {
        const categoryArr = [];
        await db.collection('users').doc(userId).collection('categories').get().then((querySnapshot) => {
          querySnapshot.forEach((doc) => {
             categoryArr.push({ id: doc.id, ...doc.data() })
          });
       })
        commit('setCategories', categoryArr);
        return categoryArr;
      } catch (err) { throw err; }
    }, 

Leave a comment