diff --git a/packages/test-e2e-composable-vue3/src/components/ChannelListPiniaContainer.vue b/packages/test-e2e-composable-vue3/src/components/ChannelListPiniaContainer.vue
new file mode 100644
index 00000000..2b5c4b03
--- /dev/null
+++ b/packages/test-e2e-composable-vue3/src/components/ChannelListPiniaContainer.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/test-e2e-composable-vue3/src/router.ts b/packages/test-e2e-composable-vue3/src/router.ts
index 6cc4027b..0ac28b7d 100644
--- a/packages/test-e2e-composable-vue3/src/router.ts
+++ b/packages/test-e2e-composable-vue3/src/router.ts
@@ -72,6 +72,13 @@ export const router = createRouter({
layout: 'blank',
},
},
+ {
+ path: '/pinia3',
+ component: () => import('./components/ChannelListPiniaContainer.vue'),
+ meta: {
+ layout: 'blank',
+ },
+ },
{
path: '/no-setup-scope-query',
component: () => import('./components/NoSetupScopeQuery.vue'),
diff --git a/packages/test-e2e-composable-vue3/tests/e2e/specs/pinia.cy.ts b/packages/test-e2e-composable-vue3/tests/e2e/specs/pinia.cy.ts
index b6762499..e13214aa 100644
--- a/packages/test-e2e-composable-vue3/tests/e2e/specs/pinia.cy.ts
+++ b/packages/test-e2e-composable-vue3/tests/e2e/specs/pinia.cy.ts
@@ -16,4 +16,15 @@ describe('Pinia', () => {
cy.contains('.channel-link', '# General')
cy.contains('.channel-link', '# Random')
})
+
+ it('works after component unmount if used in pinia', () => {
+ cy.visit('/pinia3')
+ cy.get('[data-test-id="channel-list-container"]').should('exist')
+ cy.get('[data-test-id="channel-list-toggle"]').first().click()
+ cy.get('[data-test-id="channel-list-container"]').should('not.exist')
+ cy.get('[data-test-id="channel-list-toggle"]').first().click()
+ cy.get('.channel-link').should('have.lengthOf', 2)
+ cy.contains('.channel-link', '# General')
+ cy.contains('.channel-link', '# Random')
+ })
})
diff --git a/packages/vue-apollo-composable/src/useMutation.ts b/packages/vue-apollo-composable/src/useMutation.ts
index aee637c3..28654dd2 100644
--- a/packages/vue-apollo-composable/src/useMutation.ts
+++ b/packages/vue-apollo-composable/src/useMutation.ts
@@ -1,6 +1,6 @@
import { DocumentNode } from 'graphql'
import { MutationOptions, OperationVariables, FetchResult, TypedDocumentNode, ApolloError, ApolloClient } from '@apollo/client/core/index.js'
-import { ref, onBeforeUnmount, isRef, Ref, getCurrentInstance, shallowRef } from 'vue-demi'
+import { ref, onScopeDispose, isRef, Ref, getCurrentScope, shallowRef } from 'vue-demi'
import { useApolloClient } from './useApolloClient'
import { ReactiveFunction } from './util/ReactiveFunction'
import { useEventHook } from './util/useEventHook'
@@ -53,9 +53,9 @@ export function useMutation<
document: DocumentParameter,
options: OptionsParameter = {},
): UseMutationReturn {
- const vm = getCurrentInstance()
+ const currentScope = getCurrentScope()
const loading = ref(false)
- vm && trackMutation(loading)
+ currentScope && trackMutation(loading)
const error = shallowRef(null)
const called = ref(false)
@@ -118,7 +118,7 @@ export function useMutation<
return null
}
- vm && onBeforeUnmount(() => {
+ currentScope && onScopeDispose(() => {
loading.value = false
})
diff --git a/packages/vue-apollo-composable/src/useQuery.ts b/packages/vue-apollo-composable/src/useQuery.ts
index bf340c5b..d034740c 100644
--- a/packages/vue-apollo-composable/src/useQuery.ts
+++ b/packages/vue-apollo-composable/src/useQuery.ts
@@ -5,8 +5,8 @@ import {
computed,
watch,
onServerPrefetch,
- getCurrentInstance,
- onBeforeUnmount,
+ getCurrentScope,
+ onScopeDispose,
nextTick,
shallowRef,
} from 'vue-demi'
@@ -34,8 +34,6 @@ import { trackQuery } from './util/loadingTracking'
import { resultErrorsToApolloError, toApolloError } from './util/toApolloError'
import { isServer } from './util/env'
-import type { CurrentInstance } from './util/types'
-
export interface UseQueryOptions<
// eslint-disable-next-line @typescript-eslint/no-unused-vars
TResult = any,
@@ -152,8 +150,7 @@ export function useQueryImpl<
options: OptionsParameter = {},
lazy = false,
): UseQueryReturn {
- // Is on server?
- const vm = getCurrentInstance() as CurrentInstance | null
+ const currentScope = getCurrentScope()
const currentOptions = ref>()
@@ -176,7 +173,7 @@ export function useQueryImpl<
* Indicates if a network request is pending
*/
const loading = ref(false)
- vm && trackQuery(loading)
+ currentScope && trackQuery(loading)
const networkStatus = ref()
// SSR
@@ -202,7 +199,7 @@ export function useQueryImpl<
firstRejectError = undefined
}
- vm && onServerPrefetch?.(() => {
+ currentScope && onServerPrefetch?.(() => {
if (!isEnabled.value || (isServer && currentOptions.value?.prefetch === false)) return
return new Promise((resolve, reject) => {
@@ -615,10 +612,14 @@ export function useQueryImpl<
}
// Teardown
- vm && onBeforeUnmount(() => {
- stop()
- subscribeToMoreItems.length = 0
- })
+ if (currentScope) {
+ onScopeDispose(() => {
+ stop()
+ subscribeToMoreItems.length = 0
+ })
+ } else {
+ console.warn('[Vue apollo] useQuery() is called outside of an active effect scope and the query will not be automatically stopped.')
+ }
return {
result,
diff --git a/packages/vue-apollo-composable/src/useSubscription.ts b/packages/vue-apollo-composable/src/useSubscription.ts
index b6c8e5bf..9285a52c 100644
--- a/packages/vue-apollo-composable/src/useSubscription.ts
+++ b/packages/vue-apollo-composable/src/useSubscription.ts
@@ -5,8 +5,8 @@ import {
watch,
isRef,
computed,
- getCurrentInstance,
- onBeforeUnmount,
+ getCurrentScope,
+ onScopeDispose,
nextTick,
shallowRef,
} from 'vue-demi'
@@ -27,7 +27,6 @@ import { paramToReactive } from './util/paramToReactive'
import { useApolloClient } from './useApolloClient'
import { useEventHook } from './util/useEventHook'
import { trackSubscription } from './util/loadingTracking'
-import type { CurrentInstance } from './util/types'
import { toApolloError } from './util/toApolloError'
import { isServer } from './util/env'
@@ -121,8 +120,7 @@ export function useSubscription <
variables: VariablesParameter | undefined = undefined,
options: OptionsParameter = {},
): UseSubscriptionReturn {
- // Is on server?
- const vm = getCurrentInstance() as CurrentInstance | null
+ const currentScope = getCurrentScope()
const documentRef = paramToRef(document)
const variablesRef = paramToRef(variables)
@@ -134,7 +132,7 @@ export function useSubscription <
const errorEvent = useEventHook<[ApolloError, OnErrorContext]>()
const loading = ref(false)
- vm && trackSubscription(loading)
+ currentScope && trackSubscription(loading)
// Apollo Client
const { resolveClient } = useApolloClient()
@@ -298,7 +296,11 @@ export function useSubscription <
})
// Teardown
- vm && onBeforeUnmount(stop)
+ if (currentScope) {
+ onScopeDispose(stop)
+ } else {
+ console.warn('[Vue apollo] useSubscription() is called outside of an active effect scope and the subscription will not be automatically stopped.')
+ }
return {
result,
diff --git a/packages/vue-apollo-composable/src/util/loadingTracking.ts b/packages/vue-apollo-composable/src/util/loadingTracking.ts
index 8e799ab9..7b51bebb 100644
--- a/packages/vue-apollo-composable/src/util/loadingTracking.ts
+++ b/packages/vue-apollo-composable/src/util/loadingTracking.ts
@@ -1,6 +1,8 @@
-import { Ref, watch, onUnmounted, ref, getCurrentInstance, onBeforeUnmount } from 'vue-demi'
+import { Ref, watch, onUnmounted, ref, getCurrentScope, onScopeDispose } from 'vue-demi'
import { isServer } from './env.js'
+import type { EffectScope } from 'vue-demi'
+
export interface LoadingTracking {
queries: Ref
mutations: Ref
@@ -8,7 +10,7 @@ export interface LoadingTracking {
}
export interface AppLoadingTracking extends LoadingTracking {
- components: Map
+ components: Map
}
export const globalTracking: AppLoadingTracking = {
@@ -19,26 +21,26 @@ export const globalTracking: AppLoadingTracking = {
}
export function getCurrentTracking () {
- const vm = getCurrentInstance()
- if (!vm) {
+ const currentScope = getCurrentScope()
+ if (!currentScope) {
return {}
}
let tracking: LoadingTracking
- if (!globalTracking.components.has(vm)) {
+ if (!globalTracking.components.has(currentScope)) {
// Add per-component tracking
- globalTracking.components.set(vm, tracking = {
+ globalTracking.components.set(currentScope, tracking = {
queries: ref(0),
mutations: ref(0),
subscriptions: ref(0),
})
// Cleanup
onUnmounted(() => {
- globalTracking.components.delete(vm)
+ globalTracking.components.delete(currentScope)
})
} else {
- tracking = globalTracking.components.get(vm) as LoadingTracking
+ tracking = globalTracking.components.get(currentScope) as LoadingTracking
}
return {
@@ -61,7 +63,7 @@ function track (loading: Ref, type: keyof LoadingTracking) {
immediate: true,
})
- onBeforeUnmount(() => {
+ onScopeDispose(() => {
if (loading.value) {
if (tracking) tracking[type].value--
globalTracking[type].value--
diff --git a/packages/vue-apollo-composable/src/util/types.ts b/packages/vue-apollo-composable/src/util/types.ts
deleted file mode 100644
index 8e3df908..00000000
--- a/packages/vue-apollo-composable/src/util/types.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { ComponentInternalInstance } from 'vue-demi'
-import type { AppLoadingTracking } from './loadingTracking'
-
-export interface CurrentInstance extends Omit {
- _apolloAppTracking?: AppLoadingTracking
- $root?: CurrentInstance
- root?: CurrentInstance
-}