'How to access vue router in Vuex store module actions with Quasar framework?

I am using

  • Quasar Framework v2 Beta
  • Vue 3 Composition Api
  • Vuex 4
  • Typescript

My problem:

When I import router and try to redirect User in Vuex store module actions.ts using Router.push('/') it shows me an error => Property 'push' does not exist on type 'RouteCallback<StateInterface>'

actions.ts

import { ActionTree } from 'vuex'
import { StateInterface } from '../index'
import { LoginResponseInterface } from './state'
import { api } from 'boot/axios'
import { Cookies } from 'quasar'
import Router  from '../../router'
const actions: ActionTree<LoginResponseInterface, StateInterface> = {
  UserLogin({commit}, formData){
    api.post('auth/login', formData)
    .then(response => {
      var user = {firstName: response.data.firstName, lastName: response.data.lastName, phoneNumber: response.data.phoneNumber}
      commit('setUserDetails', {token: response.data.token, user})
      Cookies.set('auth_token', response.data.token)
      Router.push('/') //`Property 'push' does not exist on type 'RouteCallback<StateInterface>'`
    })
  }
}

export default actions

router/index.ts

import { route } from 'quasar/wrappers'
import {
  createMemoryHistory,
  createRouter,
  createWebHashHistory,
  createWebHistory
} from 'vue-router'
import { StateInterface } from '../store'
import routes from './routes'

/*
 * If not building with SSR mode, you can
 * directly export the Router instantiation;
 *
 * The function below can be async too; either use
 * async/await or return a Promise which resolves
 * with the Router instance.
 */

export default route<StateInterface>(function ({ store, /* ssrContext */ } ) {
  const createHistory =
    process.env.SERVER
      ? createMemoryHistory
      : process.env.VUE_ROUTER_MODE === 'history'
        ? createWebHistory
        : createWebHashHistory

  const Router = createRouter({
    scrollBehavior: () => ({ left: 0, top: 0 }),
    routes,

    // Leave this as is and make changes in quasar.conf.js instead!
    // quasar.conf.js -> build -> vueRouterMode
    // quasar.conf.js -> build -> publicPath
    history: createHistory(
      process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE
    )
  })
 

  return Router
})



Solution 1:[1]

the problem is because of "route" wrapper which using by default in Quasar. The same trouble exists with store. I'm not sure is this wrapper required but without it all works pretty well. I just removing those wrappers and exporting directly Router object like in example below.

src/router/index.js

import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import routes from './routes'

const createHistory = process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory

export default createRouter({
  scrollBehavior: () => ({
    left: 0,
    top: 0
  }),
  routes,

  history: createHistory(process.env.VUE_ROUTER_BASE)
})

BTW, doing the same with store, works fine.

Solution 2:[2]

import { useRouter, useRoute } from 'vue-router'

Global declaration

const Router = useRouter();
const Route = useRoute();

To use the router in action

Router.push('/');

Solution 3:[3]

I believe with the new update to vue-router you can call useRouter to be able to do a push, so I suggest you make the following change in actions.ts

--- import Router  from '../../router'
+++ import { useRouter } from 'vue-router'

I hope that helps you out!

Solution 4:[4]

inside the store you can use this.$router.push('/myRoute') without importing anything at all. i am using quasar v2 as well, although I am not using typescript and I have my state/getters/mutations and actions in separate files for clarity.

Solution 5:[5]

Clearly a hack, I'm new to Vue and needed a solution in a hurry, so posting in case it helps anyone. Hopefully someone can post a better solution. Using:

  • Quasar 2.6.6
  • Vue 3 Composition API (Script Setup)
  • Vuex 4.0.1
  • Typescript

When setting a debug point in the code (with the this.$router line commented out) you can see that this.$router does indeed exist in the store action, but if you enable the line then Typescript doesn't like it and will throw a compilation error. The following ts/eslint ignores seem to shut Typescript up:

// store -> action.ts
  userClear (context) {
      console.log('clearing user data');
      // ... code to clear up the user data

      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
      this.$router.push('/login');
  },

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Taras Mykytka
Solution 2 dennisdup
Solution 3 Miguel Angel Rodriguez Jr.
Solution 4 jessie james jackson taylor
Solution 5 styl0r