vue.jsvuejs3vue-routervue-composition-api

Vue 3 Composition API useRouter() inside onMounted hook


I want to use useRoute inside my component which is called in onMounted hook. Something like

import { checkUserAuth } from '@/common/CheckUserAuth'

onMounted(async () => {
  await checkUserAuth()
})

And CheckUserAuth.ts is:

import { useRouter } from 'vue-router'

const router = useRouter() // here router is undefined

export const checkUserAuth = async () => {
  const userStore = useUserStore()
  const userApi = new UserApi()
  const token = localStorage.getItem(TOKEN_NAME)

  const router = useRouter() // and here too router is undefined

  if (!token) {
    await router.push({ name: LOGIN_PAGE_ROUTE })

    return
  }

  const userData = await userApi.fetchMasterInfo()
  userStore.setUser(userData)
  await router.push({ name: DASHBOARD_ROUTE })
}

I don't understand why the router is indefined everywhere and is it possible to solve this without passing the router as an argument? (i want to make the checkUserAuth function fully encapsulated)

i know i can fix it like

const router = useRouter()

onMounted(async () => {
  await checkUserAuth(router)
})

export const checkUserAuth = async (router: Router) => {
  await router.push({ name: DASHBOARD_ROUTE })
}

But it's not good solution


Solution

  • Composables are supposed to be used directly in setup, unless their implementation allows for other usage, this needs to be determined for each case.

    Since checkUserAuth uses composables, this makes it a composable either, in case it needs to be used in mounted hook, it needs to return a function that allows this:

    const useUserAuth = () => {
      const router = useRouter()
      const userStore = useUserStore()
      const userApi = new UserApi()
    
      return {
        async check() {...}
      }
    }
    

    Alternatively, checkUserAuth shouldn't use composables. useUserStore doesn't have restrictions that are inherent to composable, and useRouter can be replaced with an import of router instance.