From 16aa3282d38caee180201872dac4c493f6489e30 Mon Sep 17 00:00:00 2001 From: Nicolai Moraru Date: Wed, 27 Mar 2024 21:36:00 +0200 Subject: [PATCH] fix: use effect scope instead of component instance --- .../vue-apollo-composable/src/useMutation.ts | 8 +++---- .../vue-apollo-composable/src/useQuery.ts | 23 ++++++++++--------- .../src/useSubscription.ts | 14 ++++++----- .../src/util/loadingTracking.ts | 18 ++++++++------- .../vue-apollo-composable/src/util/types.ts | 8 ------- 5 files changed, 34 insertions(+), 37 deletions(-) delete mode 100644 packages/vue-apollo-composable/src/util/types.ts diff --git a/packages/vue-apollo-composable/src/useMutation.ts b/packages/vue-apollo-composable/src/useMutation.ts index f737329d..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, onScopeDispose, 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 && onScopeDispose(() => { + currentScope && onScopeDispose(() => { loading.value = false }) diff --git a/packages/vue-apollo-composable/src/useQuery.ts b/packages/vue-apollo-composable/src/useQuery.ts index e4e270d2..d034740c 100644 --- a/packages/vue-apollo-composable/src/useQuery.ts +++ b/packages/vue-apollo-composable/src/useQuery.ts @@ -5,7 +5,7 @@ import { computed, watch, onServerPrefetch, - getCurrentInstance, + getCurrentScope, onScopeDispose, nextTick, shallowRef, @@ -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 && onScopeDispose(() => { - 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 4c1b5ba4..9285a52c 100644 --- a/packages/vue-apollo-composable/src/useSubscription.ts +++ b/packages/vue-apollo-composable/src/useSubscription.ts @@ -5,7 +5,7 @@ import { watch, isRef, computed, - getCurrentInstance, + getCurrentScope, onScopeDispose, nextTick, shallowRef, @@ -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 && onScopeDispose(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 a6f98467..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, onScopeDispose } 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 { 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 -}