From 5710b3dc57bf5659aa664c6c168c9c2ab53e20cc Mon Sep 17 00:00:00 2001 From: Junhee Park <12604726+wns3645@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:45:00 +0900 Subject: [PATCH 1/3] fix(vue-query): use shallowReactive and shallowReadonly to prevent perforamcne slowdown for large datasets --- packages/vue-query/src/useBaseQuery.ts | 8 ++++---- packages/vue-query/src/useMutation.ts | 8 ++++---- packages/vue-query/src/utils.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/vue-query/src/useBaseQuery.ts b/packages/vue-query/src/useBaseQuery.ts index a50fad15aa..74c7df3fa0 100644 --- a/packages/vue-query/src/useBaseQuery.ts +++ b/packages/vue-query/src/useBaseQuery.ts @@ -2,8 +2,8 @@ import { computed, getCurrentScope, onScopeDispose, - reactive, - readonly, + shallowReactive, + shallowReadonly, toRefs, watch, } from 'vue-demi' @@ -105,7 +105,7 @@ export function useBaseQuery< }) const observer = new Observer(client, defaultedOptions.value) - const state = reactive(observer.getCurrentResult()) + const state = shallowReactive(observer.getCurrentResult()) let unsubscribe = () => { // noop @@ -201,7 +201,7 @@ export function useBaseQuery< }, ) - const object: any = toRefs(readonly(state)) + const object: any = toRefs(shallowReadonly(state)) for (const key in state) { if (typeof state[key as keyof typeof state] === 'function') { object[key] = state[key as keyof typeof state] diff --git a/packages/vue-query/src/useMutation.ts b/packages/vue-query/src/useMutation.ts index 40c336bac5..168cb11525 100644 --- a/packages/vue-query/src/useMutation.ts +++ b/packages/vue-query/src/useMutation.ts @@ -2,8 +2,8 @@ import { computed, getCurrentScope, onScopeDispose, - reactive, - readonly, + shallowReactive, + shallowReadonly, toRefs, watch, } from 'vue-demi' @@ -78,7 +78,7 @@ export function useMutation< return client.defaultMutationOptions(cloneDeepUnref(mutationOptions)) }) const observer = new MutationObserver(client, options.value) - const state = reactive(observer.getCurrentResult()) + const state = shallowReactive(observer.getCurrentResult()) const unsubscribe = observer.subscribe((result) => { updateState(state, result) @@ -101,7 +101,7 @@ export function useMutation< unsubscribe() }) - const resultRefs = toRefs(readonly(state)) as unknown as ToRefs< + const resultRefs = toRefs(shallowReadonly(state)) as unknown as ToRefs< Readonly> > diff --git a/packages/vue-query/src/utils.ts b/packages/vue-query/src/utils.ts index df68e966cd..8c73f20947 100644 --- a/packages/vue-query/src/utils.ts +++ b/packages/vue-query/src/utils.ts @@ -9,7 +9,7 @@ export function getClientKey(key?: string) { } export function updateState( - state: Record, + state: Record, update: Record, ): void { Object.keys(state).forEach((key) => { From dcd4e58e8de4cc269dca598c5721ab596e8baeea Mon Sep 17 00:00:00 2001 From: Junhee Park <12604726+wns3645@users.noreply.github.com> Date: Sat, 3 Aug 2024 16:36:46 +0900 Subject: [PATCH 2/3] Use shallowReadonly and shallowRef in useMutationState too --- packages/vue-query/src/useMutationState.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/vue-query/src/useMutationState.ts b/packages/vue-query/src/useMutationState.ts index ae9ccd6476..465c123ca0 100644 --- a/packages/vue-query/src/useMutationState.ts +++ b/packages/vue-query/src/useMutationState.ts @@ -2,13 +2,13 @@ import { computed, getCurrentScope, onScopeDispose, - readonly, - ref, + shallowReadonly, + shallowRef, watch, } from 'vue-demi' import { useQueryClient } from './useQueryClient' import { cloneDeepUnref } from './utils' -import type { DeepReadonly, Ref } from 'vue-demi' +import type { Ref } from 'vue-demi' import type { MutationFilters as MF, Mutation, @@ -68,10 +68,12 @@ function getResult( export function useMutationState( options: MutationStateOptions = {}, queryClient?: QueryClient, -): DeepReadonly>> { +): Readonly>> { const filters = computed(() => cloneDeepUnref(options.filters)) const mutationCache = (queryClient || useQueryClient()).getMutationCache() - const state = ref(getResult(mutationCache, options)) as Ref> + const state = shallowRef(getResult(mutationCache, options)) as Ref< + Array + > const unsubscribe = mutationCache.subscribe(() => { const result = getResult(mutationCache, options) state.value = result @@ -85,5 +87,5 @@ export function useMutationState( unsubscribe() }) - return readonly(state) + return shallowReadonly(state) } From a3f15f32d2b07af46cf4fb23813b234ecb1b1cd7 Mon Sep 17 00:00:00 2001 From: Damian Osipiuk Date: Wed, 4 Sep 2024 00:46:44 +0200 Subject: [PATCH 3/3] fix(vue-query): add shallow option, strip readonly in prod mode --- packages/vue-query/src/useBaseQuery.ts | 13 ++++- packages/vue-query/src/useInfiniteQuery.ts | 2 + packages/vue-query/src/useMutation.ts | 19 +++++-- packages/vue-query/src/useQueries.ts | 8 ++- packages/vue-query/src/useQuery.ts | 58 ++++++++++++---------- 5 files changed, 67 insertions(+), 33 deletions(-) diff --git a/packages/vue-query/src/useBaseQuery.ts b/packages/vue-query/src/useBaseQuery.ts index 74c7df3fa0..245a073e8b 100644 --- a/packages/vue-query/src/useBaseQuery.ts +++ b/packages/vue-query/src/useBaseQuery.ts @@ -2,6 +2,7 @@ import { computed, getCurrentScope, onScopeDispose, + readonly, shallowReactive, shallowReadonly, toRefs, @@ -145,7 +146,7 @@ export function useBaseQuery< return new Promise>( (resolve, reject) => { let stopWatch = () => { - //noop + // noop } const run = () => { if (defaultedOptions.value.enabled !== false) { @@ -201,7 +202,15 @@ export function useBaseQuery< }, ) - const object: any = toRefs(shallowReadonly(state)) + const readonlyState = + process.env.NODE_ENV === 'production' + ? state + : // @ts-expect-error + defaultedOptions.value.shallow + ? shallowReadonly(state) + : readonly(state) + + const object: any = toRefs(readonlyState) for (const key in state) { if (typeof state[key as keyof typeof state] === 'function') { object[key] = state[key as keyof typeof state] diff --git a/packages/vue-query/src/useInfiniteQuery.ts b/packages/vue-query/src/useInfiniteQuery.ts index f0e4c3134e..c4a9bcb681 100644 --- a/packages/vue-query/src/useInfiniteQuery.ts +++ b/packages/vue-query/src/useInfiniteQuery.ts @@ -49,6 +49,8 @@ export type UseInfiniteQueryOptions< TPageParam >[Property] > +} & { + shallow?: boolean } export type UseInfiniteQueryReturnType = UseBaseQueryReturnType< diff --git a/packages/vue-query/src/useMutation.ts b/packages/vue-query/src/useMutation.ts index 168cb11525..91aff2655b 100644 --- a/packages/vue-query/src/useMutation.ts +++ b/packages/vue-query/src/useMutation.ts @@ -2,6 +2,7 @@ import { computed, getCurrentScope, onScopeDispose, + readonly, shallowReactive, shallowReadonly, toRefs, @@ -26,12 +27,17 @@ type MutationResult = DistributiveOmit< 'mutate' | 'reset' > +type UseMutationOptionsBase = + MutationObserverOptions & { + shallow?: boolean + } + export type UseMutationOptions< TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown, -> = MaybeRefDeep> +> = MaybeRefDeep> type MutateSyncFunction< TData = unknown, @@ -61,7 +67,7 @@ export function useMutation< TContext = unknown, >( mutationOptions: MaybeRefDeep< - MutationObserverOptions + UseMutationOptionsBase >, queryClient?: QueryClient, ): UseMutationReturnType { @@ -101,7 +107,14 @@ export function useMutation< unsubscribe() }) - const resultRefs = toRefs(shallowReadonly(state)) as unknown as ToRefs< + const readonlyState = + process.env.NODE_ENV === 'production' + ? state + : options.value.shallow + ? shallowReadonly(state) + : readonly(state) + + const resultRefs = toRefs(readonlyState) as ToRefs< Readonly> > diff --git a/packages/vue-query/src/useQueries.ts b/packages/vue-query/src/useQueries.ts index 9300bb0ad7..371fdcc4db 100644 --- a/packages/vue-query/src/useQueries.ts +++ b/packages/vue-query/src/useQueries.ts @@ -4,6 +4,7 @@ import { getCurrentScope, onScopeDispose, readonly, + shallowReadonly, shallowRef, unref, watch, @@ -256,6 +257,7 @@ export function useQueries< }: { queries: MaybeRefDeep> combine?: (result: UseQueriesResults) => TCombinedResult + shallow?: boolean }, queryClient?: QueryClient, ): Readonly> { @@ -348,5 +350,9 @@ export function useQueries< unsubscribe() }) - return readonly(state) as Readonly> + return process.env.NODE_ENV === 'production' + ? state + : options.shallow + ? shallowReadonly(state) + : (readonly(state) as Readonly>) } diff --git a/packages/vue-query/src/useQuery.ts b/packages/vue-query/src/useQuery.ts index ad91144139..af3f1ea31d 100644 --- a/packages/vue-query/src/useQuery.ts +++ b/packages/vue-query/src/useQuery.ts @@ -23,33 +23,37 @@ export type UseQueryOptions< TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, -> = MaybeRef<{ - [Property in keyof QueryObserverOptions< - TQueryFnData, - TError, - TData, - TQueryData, - TQueryKey - >]: Property extends 'enabled' - ? MaybeRefOrGetter< - QueryObserverOptions< - TQueryFnData, - TError, - TData, - TQueryData, - DeepUnwrapRef - >[Property] - > - : MaybeRefDeep< - QueryObserverOptions< - TQueryFnData, - TError, - TData, - TQueryData, - DeepUnwrapRef - >[Property] - > -}> +> = MaybeRef< + { + [Property in keyof QueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + TQueryKey + >]: Property extends 'enabled' + ? MaybeRefOrGetter< + QueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + DeepUnwrapRef + >[Property] + > + : MaybeRefDeep< + QueryObserverOptions< + TQueryFnData, + TError, + TData, + TQueryData, + DeepUnwrapRef + >[Property] + > + } & { + shallow?: boolean + } +> export type UndefinedInitialQueryOptions< TQueryFnData = unknown,