Home > OS >  Vue 3 Composition API useRouter() inside onMounted hook
Vue 3 Composition API useRouter() inside onMounted hook

Time:08-13

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

CodePudding user response:

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.

CodePudding user response:

The API of useRouter must be called in setup, as mentioned in the official document. You can see this point in https://router.vuejs.org/zh/api/#userouter(zh document mentioned it). Maybe you can write code like this:

import { useRouter } from 'vue-router'

export const useCheckUserAuth = () => {
  const userStore = useUserStore()
  const router = useRouter()

  returnv aysnc function checkUserAuth() {
    const userApi = new UserApi()
    const token = localStorage.getItem(TOKEN_NAME)
    if (!token) {
      await router.push({ name: LOGIN_PAGE_ROUTE })
  
      return
    }
  
    const userData = await userApi.fetchMasterInfo()
    userStore.setUser(userData)
    await router.push({ name: DASHBOARD_ROUTE })
  }
}

And call it in setup:

const checkUserAuth = useCheckUserAuth()

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

hope it can help you.

  • Related