Skip to content

Commit 2af38f3

Browse files
authored
fix: support useHead outside of components (#825)
1 parent 5df4764 commit 2af38f3

File tree

1 file changed

+44
-35
lines changed

1 file changed

+44
-35
lines changed

src/runtime/composables/head.ts

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { onIonViewDidEnter, onIonViewDidLeave } from '@ionic/vue'
22
import type { ActiveHeadEntry, UseHeadInput, UseHeadOptions } from '@unhead/vue/types'
33
import type { useHead as _useHead } from '@unhead/vue'
4-
import { onBeforeUnmount } from 'vue'
4+
import { getCurrentInstance, onBeforeUnmount } from 'vue'
55
import { useRoute, useRouter } from 'vue-router'
66
import { injectHead } from '#imports'
77

@@ -16,13 +16,13 @@ let prevPath: string
1616

1717
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1818
export function useHead<T extends Record<string, any>>(obj: UseHeadInput<T>, _?: UseHeadOptions) {
19-
const currentPath = useRoute().path
19+
const instance = getCurrentInstance()
2020
const activeHead = injectHead()
21-
const { currentRoute } = useRouter()
22-
const router = useRouter()
23-
let hasReallyLeft = false
24-
let innerObj = obj
2521

22+
// vue-router composables require being called in setup
23+
const currentPath = (instance && useRoute().path) || ''
24+
25+
let innerObj = obj
2626
const __returned: Omit<ActiveHeadEntry<UseHeadInput<T>>, '_poll'> = {
2727
dispose() {
2828
// Can just easily mutate the array instead of wasting little CPU to slice/spread it :P
@@ -58,44 +58,53 @@ export function useHead<T extends Record<string, any>>(obj: UseHeadInput<T>, _?:
5858
const metaArr = headMap.get(currentPath) || []
5959
headMap.set(currentPath, [...metaArr, [obj, headObj]])
6060
}
61-
/* Clear any reference to the input Object and the bound head object before unmounting the component */
62-
onBeforeUnmount(__returned.dispose)
6361

64-
if (!beforeHook) {
65-
beforeHook = router.beforeEach(() => {
66-
prevPath = currentRoute.value.path
67-
})
68-
}
69-
if (!afterHook) {
70-
afterHook = router.afterEach(() => {
71-
currPath = currentRoute.value.path
72-
})
73-
}
62+
// Only use lifecycle hooks if called inside component setup
63+
if (instance) {
64+
const router = useRouter()
65+
const currentRoute = router!.currentRoute
7466

75-
onIonViewDidLeave(() => {
76-
let headArr = headMap.get(prevPath)
77-
if (headArr) {
78-
headArr = headArr.map(([obj, head]) => {
79-
head?.dispose()
80-
return [obj, head]
67+
/* Clear any reference to the input Object and the bound head object before unmounting the component */
68+
onBeforeUnmount(__returned.dispose)
69+
70+
if (!beforeHook) {
71+
beforeHook = router?.beforeEach(() => {
72+
prevPath = currentRoute.value.path
73+
})
74+
}
75+
if (!afterHook) {
76+
afterHook = router?.afterEach(() => {
77+
currPath = currentRoute.value.path
8178
})
82-
headMap.set(prevPath, headArr)
8379
}
84-
hasReallyLeft = true
85-
})
8680

87-
onIonViewDidEnter(() => {
88-
if (hasReallyLeft) {
89-
let headArr = headMap.get(currPath)
81+
let hasReallyLeft = false
82+
onIonViewDidLeave(() => {
83+
let headArr = headMap.get(prevPath)
9084
if (headArr) {
9185
headArr = headArr.map(([obj, head]) => {
9286
head?.dispose()
93-
const newHead = activeHead?.push(obj)
94-
return [obj, newHead]
87+
return [obj, head]
9588
})
96-
headMap.set(currPath, headArr)
89+
headMap.set(prevPath, headArr)
9790
}
98-
}
99-
})
91+
hasReallyLeft = true
92+
})
93+
94+
onIonViewDidEnter(() => {
95+
if (hasReallyLeft) {
96+
let headArr = headMap.get(currPath)
97+
if (headArr) {
98+
headArr = headArr.map(([obj, head]) => {
99+
head?.dispose()
100+
const newHead = activeHead?.push(obj)
101+
return [obj, newHead]
102+
})
103+
headMap.set(currPath, headArr)
104+
}
105+
}
106+
})
107+
}
108+
100109
return __returned
101110
}

0 commit comments

Comments
 (0)