No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Store is no longer accessible in router.

    Framework
    7
    12
    6005
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      paul last edited by

      I started a new project in the latest quasar bits.
      Unfortunately, as I used to do in previous versions, I can no longer access the vuex store in the router as follows:

      import Vue from 'vue'
      import VueRouter from 'vue-router'
      import Store from '../store/index.js'
      import routes from './routes'
      
      Vue.use(VueRouter)
      
      /*
       * If not building with SSR mode, you can
       * directly export the Router instantiation
       */
      
      export default function (/* { store, ssrContext } */) {
        const Router = new VueRouter({
          scrollBehavior: () => ({ y: 0 }),
          routes,
      
          // Leave these as is and change from quasar.conf.js instead!
          // quasar.conf.js -> build -> vueRouterMode
          mode: process.env.VUE_ROUTER_MODE,
          base: process.env.VUE_ROUTER_BASE
        })
      
        Router.beforeEach((to, from, next) => {
          console.log('calling router beforeach')
          if (!Store.getters['authentication/isAuthenticated']) {
            console.log('router beforeach: not authenticated')
            Store.dispatch('authentication/initialize')
            Store.watch(
              state => {
                return Store.getters['authentication/isAuthenticated']
              },
              value => {
                if (value === true) {
                  console.log('router beforeEach: authenticated')
                  next()
                }
              }
            )
          } else next()
        })
      
        return Router
      }
      
      

      Any idea?
      Thanks a million.
      paul.

      1 Reply Last reply Reply Quote 0
      • Hawkeye64
        Hawkeye64 last edited by

        Seems similar to mine which is working (except for the export default Router at the bottom). I’ll post it.

        Quasar CLI........ v0.17.19
        Quasar Framework.. v0.17.16
        
        import Vue from 'vue'
        import VueRouter from 'vue-router'
        
        import routes from './routes'
        import store from '../store'
        
        import JWT from 'jwt-client'
        
        Vue.use(VueRouter)
        
        const Router = new VueRouter({
          /*
           * NOTE! Change Vue Router mode from quasar.conf.js -> build -> vueRouterMode
           *
           * If you decide to go with "history" mode, please also set "build.publicPath"
           * to something other than an empty string.
           * Example: '/' instead of ''
           */
        
          // Leave as is and change from quasar.conf.js instead!
          mode: process.env.VUE_ROUTER_MODE,
          base: process.env.VUE_ROUTER_BASE,
          scrollBehavior: () => ({ y: 0 }),
          routes
        })
        
        Router.beforeEach((to, from, next) => {
          let allowedToEnter = true
          to.matched.some((record) => {
            // check if there is meta data
            let isLoggedIn = store.getters['auth/isLoggedIn']
            if (!isLoggedIn && record.name === 'home') {
              next({
                path: '/sign-in',
                replace: true
              })
              return
            }
        
            if ('meta' in record) {
              // ------------------------------------------------------------
              // check if user needs to be logged in to access this page
              if ('requiresAuth' in record.meta) {
                if (record.meta.requiresAuth) {
                  // console.log('Page requires auth:', to, from)
                  // this route requires auth, check if user is logged in
                  // if not, redirect to login page.
                  if (!isLoggedIn) {
                    // User is not logged in, redirect to signin page
                    allowedToEnter = false
                    next({
                      path: '/sign-in',
                      replace: true,
                      // redirect back to original path when done signing in
                      query: { redirect: to.fullPath }
                    })
                  }
                }
              }
              // ------------------------------------------------------------
              // check if user has correct permissions to access this page
              if (allowedToEnter && 'permissions' in record.meta) {
                let canProceed = false
                let permissions = record.meta.permissions
                // get currently logged in user permissions
                let token = store.getters['auth/token']
                // decipher the token
                let session = JWT.read(token)
                // check if they are not an admin (administrator)
                if (session.claim.permissions.administrator) {
                  canProceed = true
                }
                else {
                  for (let index = 0; index < permissions.length; ++index) {
                    let permission = permissions[index]
                    // console.log('Permission needed:', permission)
                    if (permission === 'administrator') {
                      if (session.claim.permissions.administrator) {
                        canProceed = true
                      }
                    }
                    else if (permission === 'liveview') {
                      if (session.claim.permissions.liveview) {
                        canProceed = true
                      }
                    }
                    else if (permission === 'archive') {
                      if (session.claim.permissions.archive) {
                        canProceed = true
                      }
                    }
                    else if (permission === 'alarmsArchiveEvents') {
                      if (session.claim.permissions.alarmsArchiveEvents) {
                        canProceed = true
                      }
                    }
                    else if (permission === 'remoteAccess') {
                      if (session.claim.permissions.remoteAccess) {
                        canProceed = true
                      }
                    }
                    else if (permission === 'settings') {
                      if (session.claim.permissions.settings) {
                        canProceed = true
                      }
                    }
                    else {
                      console.error('Unknown permission in Router.beforeEach:', permission)
                    }
                  }
                }
        
                if (!canProceed) {
                  allowedToEnter = false
                  // redirect to not-authorized page
                  next({
                    path: '/not-authorized',
                    replace: true
                  })
                }
              }
            }
          })
        
          if (allowedToEnter) {
            // go to the requested page
            next()
          }
        })
        
        export default Router
        
        1 Reply Last reply Reply Quote 1
        • P
          paul last edited by paul

          @Hawkeye64 Thanks a lot for your support.

          I created via the cli a brand new project which illustrates the problem in the most simple way.

          https://github.com/paulvanbladel/quasar-demo

          Basically, it happens here:

            Router.beforeEach((to, from, next) => {
              console.log('before each')
              console.log(store.state.example.test)
              next()
            })
          1 Reply Last reply Reply Quote 0
          • P
            paul last edited by

            solved.
            When implementing the beforeEach in a plugin, it works 🙂

            export default ({ router, store, Vue }) => {
              router.beforeEach((to, from, next) => {
                console.log('before each')
                debugger
                console.log(store.state.example.test)
                next()
              })
            }
            
            1 Reply Last reply Reply Quote 2
            • metalsadman
              metalsadman last edited by metalsadman

              you could’ve just un-commented the line.
              export default function (/* { store, ssrContext } */) {
              to
              export default function ({ store }) {
              also comment the line
              import store from '../store'
              since like doing it with quasar plugins, the store is also accessible in router/index.js.

              alhidalgodev 2 Replies Last reply Reply Quote 3
              • J
                jacklin10 last edited by jacklin10

                I couldn’t get this to work by using the getters either.

                // router/index.js
                import store from '../store/auth'
                
                  Router.beforeEach((to, from, next) => {
                      // works
                      console.log('loggedIn: ', store.state.loggedIn)
                      // flailing failed attempts while hammering the keyboard and looking to the sky for answers
                      console.log('LoggedIn: ', store.getters['auth/loggedIn'])
                      console.log('LoggedIn: ', store.getters.loggedIn)
                      console.log('LoggedIn: ', store.loggedIn)
                  })```
                1 Reply Last reply Reply Quote 0
                • metalsadman
                  metalsadman last edited by metalsadman

                  @jacklin10 be sure that you passed the store as an arg at your router/index.js’s export default function to access the store You don’t need to import your store.
                  Like I stated on my older reply in this thread https://forum.quasar-framework.org/topic/2825/store-is-no-longer-accessible-in-router/6… which is just above your post.
                  ie.

                  export default function({ store }) { // <<<<<<-- this is what you're looking for
                    const Router = new VueRouter({
                      scrollBehavior: () => ({ x: 0, y: 0 }),
                      routes,
                      mode: process.env.VUE_ROUTER_MODE,
                      base: process.env.VUE_ROUTER_BASE
                    })
                  
                    Router.beforeEach((to, from, next) => {
                        ...
                        console.log('LoggedIn: ', store.getters['auth/loggedIn'])
                        ....
                    })
                  
                    return Router
                  }
                  
                  1 Reply Last reply Reply Quote 3
                  • M
                    matzeso last edited by matzeso

                    Hey,
                    I am also having problems getting to the store from my routes. I want to use a guard only on specific parent routes and this guard needs access to the store. My router/index can have {store} in the export function part, but I need it within my guard, which is imported within my routes.js, which in turn is imported from router/index. So I don’t know how it would help me that I can inject the { store } in my router/index as I need it in other modules.

                    Since the store exports a function, I just called this function to receive it, but I am getting a lot of "don’t mutate the store directly’ messages, although none of my actions does anything to the state directly.

                    This is my guard:

                    import {actions} from '@store/auth/actions';
                    import getStore from '@store';
                    
                    export const loggedInGuard = async (to, from, next) => {
                        let store = getStore();
                        if (store.getters.isLoggedIn) {
                            return next();
                        }
                    
                        try {
                            await store.dispatch(actions.LOGIN);
                        } catch(e) {
                    
                        }
                    
                        if (store.getters.isLoggedIn) {
                            next();
                        } else {
                            next({name: 'login', query: {redirect: to.fullPath}});
                        }
                    }
                    

                    And this is my login action:

                    async [actions.LOGIN]({ dispatch, commit, state}) {
                            let response = {};
                    
                            try {
                    
                                response = await axios({
                                    url: `${constants.API_URL}/user`,
                                    method: 'get',
                                });
                    
                                if (response.payload && response.payload.data) {
                                    commit(mutations.SET_LOGGED_IN_USER, response.payload.data);
                                    return Promise.resolve(true);
                                }
                    
                    
                            } catch (e) {
                             
                            }
                    
                            return Promise.reject('User data could not be retrieved');
                        }
                    

                    The commit(mutations.SET_LOGGED_IN_USER, response.payload.data); does have 2 lines only, where I am just doing something like this.state.user = user and another similar line, and they both throw 2 errors, reading:

                    Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers."
                    vue.runtime.esm.js?2b0e:1888 Error: [vuex] do not mutate vuex store state outside mutation handlers.
                        at assert (vuex.esm.js?2f62:90)
                        at Vue.store._vm.$watch.deep (vuex.esm.js?2f62:774)
                        at Watcher.run (vue.runtime.esm.js?2b0e:4562)
                        at Watcher.update (vue.runtime.esm.js?2b0e:4536)
                        at Dep.notify (vue.runtime.esm.js?2b0e:730)
                        at Object.reactiveSetter [as user] (vue.runtime.esm.js?2b0e:1055)
                        at Store.eval (mutations.js?a46e:17)
                        at wrappedMutationHandler (vuex.esm.js?2f62:725)
                        at commitIterator (vuex.esm.js?2f62:391)
                        at Array.forEach (<anonymous>)
                    

                    I would really appreciate some help 🙂 I am trying to figure this out for hours now and I just don’t get why these errors come up… 😕

                    V 1 Reply Last reply Reply Quote 0
                    • metalsadman
                      metalsadman last edited by

                      @matzeso please make a separate topic next time, yours is not related to the original question. while this question has been probably asked multiple times here and somewhere else, like this one https://github.com/nuxt/nuxt.js/issues/1917.

                      1 Reply Last reply Reply Quote 1
                      • V
                        vildar @matzeso last edited by vildar

                        @matzeso I came to this topc with the exact problem and my “solution” looked like yours, so I think it’s relevant here. I’ve now a solution which is somewhat a workaround but still playing by the rules. I use route meta fields in routes.js and markup any route that should have my auth guard with requiredAuth meta field.

                        const routes = [
                          {
                            path: '/home',
                            component: () => import('layouts/BaseLayout.vue'),
                            children: [
                              { path: '',
                                name: 'pagename',
                                meta: { requireAuth: true },
                                component: () => import('pages/HomePageName.vue') }
                            ]
                          }
                        ]
                        

                        In router/index.js I then I pass store as an argument in the export default function and implement a beforeEach that checks the meta field. So the guard that require access to the store and a getter, is moved into a beforeEach function. It’s not strictly the same but good enough for me.

                        export default function ({ store }) {
                          const Router = new VueRouter({
                          ...
                          })
                        
                          Router.beforeEach((to, from, next) => {
                            if (to.matched.some(record => record.meta.requireAuth)) {
                              if (store.getters['auth/isSignedIn']) {
                                next()
                              } else {
                                next({ name: 'account-signin', query: { next: to.fullPath } })
                              }
                            } else {
                              next()
                            }
                          })
                        
                          return Router
                        }
                        

                        So a little mix of previous replies by @metalsadman and others, with other parts of vue-router made it work for me.

                        1 Reply Last reply Reply Quote 0
                        • alhidalgodev
                          alhidalgodev @metalsadman last edited by

                          This post is deleted!
                          1 Reply Last reply Reply Quote 0
                          • alhidalgodev
                            alhidalgodev @metalsadman last edited by

                            @metalsadman said in Store is no longer accessible in router.:

                            you could’ve just un-commented the line.
                            export default function (/* { store, ssrContext } */) {
                            to
                            export default function ({ store }) {
                            also comment the line
                            import store from '../store'
                            since like doing it with quasar plugins, the store is also accessible in router/index.js.

                            Work perfect for me in quasar 1.4.0

                            1 Reply Last reply Reply Quote 0
                            • First post
                              Last post