diff --git a/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch b/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch new file mode 100644 index 000000000000..aac618f0c4ac --- /dev/null +++ b/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch @@ -0,0 +1,830 @@ +diff --git a/build/legacy/useBaseQuery.cjs b/build/legacy/useBaseQuery.cjs +index b64ea5c5f9389e560ce6fd850dd3d52e8d2e6e73..82bfe43c9b2feeab44afe533aa0c70a3647ea627 100644 +--- a/build/legacy/useBaseQuery.cjs ++++ b/build/legacy/useBaseQuery.cjs +@@ -35,6 +35,7 @@ __export(useBaseQuery_exports, { + }); + module.exports = __toCommonJS(useBaseQuery_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + var import_QueryErrorResetBoundary = require("./QueryErrorResetBoundary.cjs"); +@@ -71,7 +72,7 @@ function useBaseQuery(options, Observer, queryClient) { + ) + ); + const result = observer.getOptimisticResult(defaultedOptions); +- React.useSyncExternalStore( ++ (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => { + const unsubscribe = isRestoring ? import_utils.noop : observer.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)); +diff --git a/build/legacy/useBaseQuery.cjs.map b/build/legacy/useBaseQuery.cjs.map +index 0dad9cfafd6c15e84683ec40137a1cfa405a930b..46d962e7df4713b5d09a5aa4dba8d07abadd7a57 100644 +--- a/build/legacy/useBaseQuery.cjs.map ++++ b/build/legacy/useBaseQuery.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AAEvB,wBAAwC;AACxC,iCAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,yBAA+B;AAC/B,sBAKO;AACP,mBAAqB;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AA3CtC;AA4CE,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,8BAA5C;AAAA;AAAA,IACA;AAAA;AAIF,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,4CAAqB,gBAAgB;AACrC,iEAAgC,kBAAkB,kBAAkB;AAEpE,4DAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,UAAI,+BAAc,kBAAkB,MAAM,GAAG;AAC3C,cAAM,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,UACE,uCAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,6BAA5C;AAAA;AAAA,IACA;AAAA,IACA;AAAA;AAGF,MACE,iBAAiB,iCACjB,CAAC,kCACD,2BAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,UAEZ,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,OAE9D,YAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,MAArD,mBAAwD;AAAA;AAE5D,uCAAS,MAAM,mBAAM,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB;AAAA,EACF;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAAwC;AACxC,iCAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,yBAA+B;AAC/B,sBAKO;AACP,mBAAqB;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AA5CtC;AA6CE,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,8BAA5C;AAAA;AAAA,IACA;AAAA;AAIF,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,4CAAqB,gBAAgB;AACrC,iEAAgC,kBAAkB,kBAAkB;AAEpE,4DAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D;AAAA,IACQ;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,UAAI,+BAAc,kBAAkB,MAAM,GAAG;AAC3C,cAAM,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,UACE,uCAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,6BAA5C;AAAA;AAAA,IACA;AAAA,IACA;AAAA;AAGF,MACE,iBAAiB,iCACjB,CAAC,kCACD,2BAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,UAEZ,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,OAE9D,YAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,MAArD,mBAAwD;AAAA;AAE5D,uCAAS,MAAM,mBAAM,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB;AAAA,EACF;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useBaseQuery.js b/build/legacy/useBaseQuery.js +index daadb39a71bcb61c20aab33031b2c8be5a02df42..52f4e2ba490165672001eac667e008099da286c4 100644 +--- a/build/legacy/useBaseQuery.js ++++ b/build/legacy/useBaseQuery.js +@@ -2,6 +2,7 @@ + + // src/useBaseQuery.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { isServer, notifyManager } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + import { useQueryErrorResetBoundary } from "./QueryErrorResetBoundary.js"; +@@ -47,7 +48,7 @@ function useBaseQuery(options, Observer, queryClient) { + ) + ); + const result = observer.getOptimisticResult(defaultedOptions); +- React.useSyncExternalStore( ++ useSyncExternalStore( + React.useCallback( + (onStoreChange) => { + const unsubscribe = isRestoring ? noop : observer.subscribe(notifyManager.batchCalls(onStoreChange)); +diff --git a/build/legacy/useBaseQuery.js.map b/build/legacy/useBaseQuery.js.map +index c4d3cbf5623b5f9869df7d4cc7da99e61cd97cba..9db12605d968f471b72dc91559216e3b13e6acdd 100644 +--- a/build/legacy/useBaseQuery.js.map ++++ b/build/legacy/useBaseQuery.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AAEvB,SAAS,UAAU,qBAAqB;AACxC,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AA3CtC;AA4CE,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,8BAA5C;AAAA;AAAA,IACA;AAAA;AAIF,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,uBAAqB,gBAAgB;AACrC,kCAAgC,kBAAkB,kBAAkB;AAEpE,6BAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,MAAI,cAAc,kBAAkB,MAAM,GAAG;AAC3C,UAAM,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,MACE,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,6BAA5C;AAAA;AAAA,IACA;AAAA,IACA;AAAA;AAGF,MACE,iBAAiB,iCACjB,CAAC,YACD,UAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,MAEZ,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,OAE9D,YAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,MAArD,mBAAwD;AAAA;AAE5D,uCAAS,MAAM,MAAM,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB;AAAA,EACF;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,UAAU,qBAAqB;AACxC,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AA5CtC;AA6CE,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,8BAA5C;AAAA;AAAA,IACA;AAAA;AAIF,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,uBAAqB,gBAAgB;AACrC,kCAAgC,kBAAkB,kBAAkB;AAEpE,6BAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D;AAAA,IACQ;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,MAAI,cAAc,kBAAkB,MAAM,GAAG;AAC3C,UAAM,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,MACE,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,GAAC,kBAAO,kBAAkB,EAAE,YAA3B,mBAA4C,6BAA5C;AAAA;AAAA,IACA;AAAA,IACA;AAAA;AAGF,MACE,iBAAiB,iCACjB,CAAC,YACD,UAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,MAEZ,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,OAE9D,YAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,MAArD,mBAAwD;AAAA;AAE5D,uCAAS,MAAM,MAAM,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB;AAAA,EACF;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useIsFetching.cjs b/build/legacy/useIsFetching.cjs +index 28660e7d19489acc86f6a2f0c9b47e453ac66fae..2bed8ddef2f97adfb60c35aa83630259898e5e20 100644 +--- a/build/legacy/useIsFetching.cjs ++++ b/build/legacy/useIsFetching.cjs +@@ -35,12 +35,13 @@ __export(useIsFetching_exports, { + }); + module.exports = __toCommonJS(useIsFetching_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + function useIsFetching(filters, queryClient) { + const client = (0, import_QueryClientProvider.useQueryClient)(queryClient); + const queryCache = client.getQueryCache(); +- return React.useSyncExternalStore( ++ return (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => queryCache.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)), + [queryCache] +diff --git a/build/legacy/useIsFetching.cjs.map b/build/legacy/useIsFetching.cjs.map +index 5a58e86806e2919b9dcfbaf0cc3c32a4e23a5661..d3d112b618dc78caf24b36510852fdd647381c0a 100644 +--- a/build/legacy/useIsFetching.cjs.map ++++ b/build/legacy/useIsFetching.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,wBAA8B;AAE9B,iCAA+B;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAA8B;AAE9B,iCAA+B;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,aAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useIsFetching.js b/build/legacy/useIsFetching.js +index acfc67a302d371b13b632cfdfcba1740ac6cfa22..90af8d148cbedb97df0b11b64fe84b4db973acd4 100644 +--- a/build/legacy/useIsFetching.js ++++ b/build/legacy/useIsFetching.js +@@ -2,12 +2,13 @@ + + // src/useIsFetching.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { notifyManager } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + function useIsFetching(filters, queryClient) { + const client = useQueryClient(queryClient); + const queryCache = client.getQueryCache(); +- return React.useSyncExternalStore( ++ return useSyncExternalStore( + React.useCallback( + (onStoreChange) => queryCache.subscribe(notifyManager.batchCalls(onStoreChange)), + [queryCache] +diff --git a/build/legacy/useIsFetching.js.map b/build/legacy/useIsFetching.js.map +index 9921ab6e20952d564197ef61fccc3ab1f4943bd0..4b13c50e8e70381758c583c3b8cfbd0180d13a04 100644 +--- a/build/legacy/useIsFetching.js.map ++++ b/build/legacy/useIsFetching.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,qBAAqB;AAE9B,SAAS,sBAAsB;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,qBAAqB;AAE9B,SAAS,sBAAsB;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,SAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useMutation.cjs b/build/legacy/useMutation.cjs +index 175de467172e7c876d51141d22f151de482d2a43..826a83d5f08d22035d1f8bd31a0236299055dec3 100644 +--- a/build/legacy/useMutation.cjs ++++ b/build/legacy/useMutation.cjs +@@ -35,6 +35,7 @@ __export(useMutation_exports, { + }); + module.exports = __toCommonJS(useMutation_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + var import_utils = require("./utils.cjs"); +@@ -49,7 +50,7 @@ function useMutation(options, queryClient) { + React.useEffect(() => { + observer.setOptions(options); + }, [observer, options]); +- const result = React.useSyncExternalStore( ++ const result = (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => observer.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)), + [observer] +diff --git a/build/legacy/useMutation.cjs.map b/build/legacy/useMutation.cjs.map +index 2beaf7a697d67be63bb22ae4739b0db0eeede8f7..ffd27eb4f52319afc1afa4122c9982f6484591bd 100644 +--- a/build/legacy/useMutation.cjs.map ++++ b/build/legacy/useMutation.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,wBAAgD;AAChD,iCAA+B;AAC/B,mBAAuC;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,aAAS,2CAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,SAAe;AAAA,IACb;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,iBAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,aACP,+BAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAAgD;AAChD,iCAA+B;AAC/B,mBAAuC;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,aAAS,2CAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,aAAS;AAAA,IACP;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,iBAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,aACP,+BAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useMutation.js b/build/legacy/useMutation.js +index 515a3b92ecf8c348ccc7f16de4f778301327e9c9..a135e33b89a5cf9ef8d1725a9aada6283052bed9 100644 +--- a/build/legacy/useMutation.js ++++ b/build/legacy/useMutation.js +@@ -2,6 +2,7 @@ + + // src/useMutation.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { MutationObserver, notifyManager } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + import { noop, shouldThrowError } from "./utils.js"; +@@ -16,7 +17,7 @@ function useMutation(options, queryClient) { + React.useEffect(() => { + observer.setOptions(options); + }, [observer, options]); +- const result = React.useSyncExternalStore( ++ const result = useSyncExternalStore( + React.useCallback( + (onStoreChange) => observer.subscribe(notifyManager.batchCalls(onStoreChange)), + [observer] +diff --git a/build/legacy/useMutation.js.map b/build/legacy/useMutation.js.map +index 0627ad75983fcc9d6cd9d66a20f7a935dd076ad4..03013010c6b9d825c2888d9ac03edc774e8b7965 100644 +--- a/build/legacy/useMutation.js.map ++++ b/build/legacy/useMutation.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,kBAAkB,qBAAqB;AAChD,SAAS,sBAAsB;AAC/B,SAAS,MAAM,wBAAwB;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,SAAS,eAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,SAAe;AAAA,IACb;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,IAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,SACP,iBAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,kBAAkB,qBAAqB;AAChD,SAAS,sBAAsB;AAC/B,SAAS,MAAM,wBAAwB;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,SAAS,eAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,SAAS;AAAA,IACP;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,IAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,SACP,iBAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useMutationState.cjs b/build/legacy/useMutationState.cjs +index 0248bea1b0a0922589748a9338d85be66fc3468c..0bb6d8ac2eacb572b35c29429ef5d94edf33b7ad 100644 +--- a/build/legacy/useMutationState.cjs ++++ b/build/legacy/useMutationState.cjs +@@ -36,6 +36,7 @@ __export(useMutationState_exports, { + }); + module.exports = __toCommonJS(useMutationState_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + function useIsMutating(filters, queryClient) { +@@ -60,7 +61,7 @@ function useMutationState(options = {}, queryClient) { + React.useEffect(() => { + optionsRef.current = options; + }); +- return React.useSyncExternalStore( ++ return (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => mutationCache.subscribe(() => { + const nextResult = (0, import_query_core.replaceEqualDeep)( +diff --git a/build/legacy/useMutationState.cjs.map b/build/legacy/useMutationState.cjs.map +index 68b0a392336cba75982a1146353c1e14698fca14..6383002ae8e9b97a4390db3bcead0e1955925ac6 100644 +--- a/build/legacy/useMutationState.cjs.map ++++ b/build/legacy/useMutationState.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,YAAuB;AAEvB,wBAAgD;AAChD,iCAA+B;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,oBAAgB,2CAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,iBAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,0CAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,YAAuB;AACvB,kBAAqC;AAErC,wBAAgD;AAChD,iCAA+B;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,oBAAgB,2CAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,aAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,iBAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,0CAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useMutationState.js b/build/legacy/useMutationState.js +index 0648af4cfd70499f3365abc8b63a06e06976f793..2345f0eecff02f33f0354832b94ce0fdfa31540e 100644 +--- a/build/legacy/useMutationState.js ++++ b/build/legacy/useMutationState.js +@@ -2,6 +2,7 @@ + + // src/useMutationState.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { notifyManager, replaceEqualDeep } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + function useIsMutating(filters, queryClient) { +@@ -26,7 +27,7 @@ function useMutationState(options = {}, queryClient) { + React.useEffect(() => { + optionsRef.current = options; + }); +- return React.useSyncExternalStore( ++ return useSyncExternalStore( + React.useCallback( + (onStoreChange) => mutationCache.subscribe(() => { + const nextResult = replaceEqualDeep( +diff --git a/build/legacy/useMutationState.js.map b/build/legacy/useMutationState.js.map +index ae13415e7f9c31177b3ccd37a92ba91b10385705..aa4027b3c846be5f0f769339aee4ff1ac2c0de82 100644 +--- a/build/legacy/useMutationState.js.map ++++ b/build/legacy/useMutationState.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;AAGA,YAAY,WAAW;AAEvB,SAAS,eAAe,wBAAwB;AAChD,SAAS,sBAAsB;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,gBAAgB,eAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,aAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,wBAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;AAGA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,eAAe,wBAAwB;AAChD,SAAS,sBAAsB;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,gBAAgB,eAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,SAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,aAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,wBAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useQueries.cjs b/build/legacy/useQueries.cjs +index 30624c08a79ccc7bdb806089683cacf0fd3a7223..03e98d4603058cb15e644a23330ffea99a92b1c8 100644 +--- a/build/legacy/useQueries.cjs ++++ b/build/legacy/useQueries.cjs +@@ -35,6 +35,7 @@ __export(useQueries_exports, { + }); + module.exports = __toCommonJS(useQueries_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + var import_isRestoring = require("./isRestoring.cjs"); +@@ -75,7 +76,7 @@ function useQueries({ + defaultedQueries, + options.combine + ); +- React.useSyncExternalStore( ++ (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => isRestoring ? import_utils.noop : observer.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)), + [observer, isRestoring] +diff --git a/build/legacy/useQueries.cjs.map b/build/legacy/useQueries.cjs.map +index 7b475fbe921935d164f0d29821f068d25281b048..cf2556492a71ceff6c8acfc5ddec4a833de75de7 100644 +--- a/build/legacy/useQueries.cjs.map ++++ b/build/legacy/useQueries.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AAEvB,wBAIO;AACP,iCAA+B;AAC/B,yBAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,sBAKO;AACP,mBAAqB;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,8CAAqB,KAAK;AAC1B,mEAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,4DAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBACC,cACI,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,cAC7D,+BAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,gCAAc,QAAQ,IAAI;AACpD,cAAI,+BAAc,MAAM,MAAM,GAAG;AAC/B,mBAAO,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,eAAW,2BAAU,QAAQ,WAAW,GAAG;AACzC,iBAAK,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,aACA,uCAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,uFAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAIO;AACP,iCAA+B;AAC/B,yBAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,sBAKO;AACP,mBAAqB;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,8CAAqB,KAAK;AAC1B,mEAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,4DAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF;AAAA,IACQ;AAAA,MACJ,CAAC,kBACC,cACI,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,cAC7D,+BAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,gCAAc,QAAQ,IAAI;AACpD,cAAI,+BAAc,MAAM,MAAM,GAAG;AAC/B,mBAAO,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,eAAW,2BAAU,QAAQ,WAAW,GAAG;AACzC,iBAAK,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,aACA,uCAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,uFAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file +diff --git a/build/legacy/useQueries.js b/build/legacy/useQueries.js +index fe5a1a787a1c9419ba2601dd0e15d738bac0a24b..d440e604085f75127ce7800bf29c10c97df4b319 100644 +--- a/build/legacy/useQueries.js ++++ b/build/legacy/useQueries.js +@@ -2,6 +2,7 @@ + + // src/useQueries.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { + QueriesObserver, + QueryObserver, +@@ -55,7 +56,7 @@ function useQueries({ + defaultedQueries, + options.combine + ); +- React.useSyncExternalStore( ++ useSyncExternalStore( + React.useCallback( + (onStoreChange) => isRestoring ? noop : observer.subscribe(notifyManager.batchCalls(onStoreChange)), + [observer, isRestoring] +diff --git a/build/legacy/useQueries.js.map b/build/legacy/useQueries.js.map +index b4e19659cea057b7421f374e1a3a45f882225ba2..49c8e1f60074ef0ae796cc179522aa84cabd9e57 100644 +--- a/build/legacy/useQueries.js.map ++++ b/build/legacy/useQueries.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AAEvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,yBAAqB,KAAK;AAC1B,oCAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,6BAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBACC,cACI,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,UAC7D,cAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,cAAc,QAAQ,IAAI;AACpD,UAAI,cAAc,MAAM,MAAM,GAAG;AAC/B,eAAO,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,WAAW,UAAU,QAAQ,WAAW,GAAG;AACzC,aAAK,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,SACA,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,uFAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,yBAAqB,KAAK;AAC1B,oCAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,6BAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF;AAAA,IACQ;AAAA,MACJ,CAAC,kBACC,cACI,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,UAC7D,cAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,cAAc,QAAQ,IAAI;AACpD,UAAI,cAAc,MAAM,MAAM,GAAG;AAC/B,eAAO,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,WAAW,UAAU,QAAQ,WAAW,GAAG;AACzC,aAAK,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,SACA,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,uFAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useBaseQuery.cjs b/build/modern/useBaseQuery.cjs +index 6b9f949241b8f5dad782c53d96da7a39c22bfeb9..88322155c346a4ce714520ebba0ea954aa128fd0 100644 +--- a/build/modern/useBaseQuery.cjs ++++ b/build/modern/useBaseQuery.cjs +@@ -35,6 +35,7 @@ __export(useBaseQuery_exports, { + }); + module.exports = __toCommonJS(useBaseQuery_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + var import_QueryErrorResetBoundary = require("./QueryErrorResetBoundary.cjs"); +@@ -69,7 +70,7 @@ function useBaseQuery(options, Observer, queryClient) { + ) + ); + const result = observer.getOptimisticResult(defaultedOptions); +- React.useSyncExternalStore( ++ (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => { + const unsubscribe = isRestoring ? import_utils.noop : observer.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)); +diff --git a/build/modern/useBaseQuery.cjs.map b/build/modern/useBaseQuery.cjs.map +index ad9c36de61b6137af70c2432d06d1885250d9c2a..42dc165d1b2aa3f25822a4588f994f461e5ab199 100644 +--- a/build/modern/useBaseQuery.cjs.map ++++ b/build/modern/useBaseQuery.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AAEvB,wBAAwC;AACxC,iCAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,yBAA+B;AAC/B,sBAKO;AACP,mBAAqB;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AACpC,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,EACF;AAGA,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,4CAAqB,gBAAgB;AACrC,iEAAgC,kBAAkB,kBAAkB;AAEpE,4DAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,UAAI,+BAAc,kBAAkB,MAAM,GAAG;AAC3C,cAAM,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,UACE,uCAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,IACA;AAAA,EACF;AAEA,MACE,iBAAiB,iCACjB,CAAC,kCACD,2BAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,UAEZ,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,MAE9D,OAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,GAAG;AAAA;AAE5D,aAAS,MAAM,iBAAI,EAAE,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB,CAAC;AAAA,EACH;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAAwC;AACxC,iCAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,yBAA+B;AAC/B,sBAKO;AACP,mBAAqB;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AACpC,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,EACF;AAGA,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,4CAAqB,gBAAgB;AACrC,iEAAgC,kBAAkB,kBAAkB;AAEpE,4DAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D;AAAA,IACQ;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,UAAI,+BAAc,kBAAkB,MAAM,GAAG;AAC3C,cAAM,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,UACE,uCAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,IACA;AAAA,EACF;AAEA,MACE,iBAAiB,iCACjB,CAAC,kCACD,2BAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,UAEZ,iCAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,MAE9D,OAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,GAAG;AAAA;AAE5D,aAAS,MAAM,iBAAI,EAAE,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB,CAAC;AAAA,EACH;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useBaseQuery.js b/build/modern/useBaseQuery.js +index e8cf3a4fba4c6f8ddbbdf8ebd3fdad054a059d0c..9758bc05f3f2b76c980a7b52276c95e7db1a8ac8 100644 +--- a/build/modern/useBaseQuery.js ++++ b/build/modern/useBaseQuery.js +@@ -2,6 +2,7 @@ + + // src/useBaseQuery.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { isServer, notifyManager } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + import { useQueryErrorResetBoundary } from "./QueryErrorResetBoundary.js"; +@@ -45,7 +46,7 @@ function useBaseQuery(options, Observer, queryClient) { + ) + ); + const result = observer.getOptimisticResult(defaultedOptions); +- React.useSyncExternalStore( ++ useSyncExternalStore( + React.useCallback( + (onStoreChange) => { + const unsubscribe = isRestoring ? noop : observer.subscribe(notifyManager.batchCalls(onStoreChange)); +diff --git a/build/modern/useBaseQuery.js.map b/build/modern/useBaseQuery.js.map +index b84572b8d8230d96a606652f24faf97f3ff366e4..13bb6e0982b96216f9c90d97a69a2ac3adb6274b 100644 +--- a/build/modern/useBaseQuery.js.map ++++ b/build/modern/useBaseQuery.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AAEvB,SAAS,UAAU,qBAAqB;AACxC,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AACpC,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,EACF;AAGA,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,uBAAqB,gBAAgB;AACrC,kCAAgC,kBAAkB,kBAAkB;AAEpE,6BAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,MAAI,cAAc,kBAAkB,MAAM,GAAG;AAC3C,UAAM,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,MACE,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,IACA;AAAA,EACF;AAEA,MACE,iBAAiB,iCACjB,CAAC,YACD,UAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,MAEZ,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,MAE9D,OAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,GAAG;AAAA;AAE5D,aAAS,MAAM,IAAI,EAAE,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB,CAAC;AAAA,EACH;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useBaseQuery.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { isServer, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport { useIsRestoring } from './isRestoring'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n QueryClient,\n QueryKey,\n QueryObserver,\n QueryObserverResult,\n} from '@tanstack/query-core'\nimport type { UseBaseQueryOptions } from './types'\n\nexport function useBaseQuery<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey extends QueryKey,\n>(\n options: UseBaseQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryData,\n TQueryKey\n >,\n Observer: typeof QueryObserver,\n queryClient?: QueryClient,\n): QueryObserverResult {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof options !== 'object' || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object',\n )\n }\n }\n\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n const defaultedOptions = client.defaultQueryOptions(options)\n\n ;(client.getDefaultOptions().queries as any)?._experimental_beforeQuery?.(\n defaultedOptions,\n )\n\n // Make sure results are optimistically set in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n ensureSuspenseTimers(defaultedOptions)\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary)\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n // this needs to be invoked before creating the Observer because that can create a cache entry\n const isNewCacheEntry = !client\n .getQueryCache()\n .get(defaultedOptions.queryHash)\n\n const [observer] = React.useState(\n () =>\n new Observer(\n client,\n defaultedOptions,\n ),\n )\n\n const result = observer.getOptimisticResult(defaultedOptions)\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange))\n\n // Update result to make sure we did not miss any query updates\n // between creating the observer and subscribing to it.\n observer.updateResult()\n\n return unsubscribe\n },\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setOptions(defaultedOptions, { listeners: false })\n }, [defaultedOptions, observer])\n\n // Handle suspense\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n }\n\n // Handle error boundary\n if (\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query: client\n .getQueryCache()\n .get<\n TQueryFnData,\n TError,\n TQueryData,\n TQueryKey\n >(defaultedOptions.queryHash),\n })\n ) {\n throw result.error\n }\n\n ;(client.getDefaultOptions().queries as any)?._experimental_afterQuery?.(\n defaultedOptions,\n result,\n )\n\n if (\n defaultedOptions.experimental_prefetchInRender &&\n !isServer &&\n willFetch(result, isRestoring)\n ) {\n const promise = isNewCacheEntry\n ? // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n : // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n client.getQueryCache().get(defaultedOptions.queryHash)?.promise\n\n promise?.catch(noop).finally(() => {\n // `.updateResult()` will trigger `.#currentThenable` to finalize\n observer.updateResult()\n })\n }\n\n // Handle result property usage tracking\n return !defaultedOptions.notifyOnChangeProps\n ? observer.trackResult(result)\n : result\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,UAAU,qBAAqB;AACxC,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AASd,SAAS,aAOd,SAOA,UACA,aACoC;AACpC,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACzD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AACtD,QAAM,mBAAmB,OAAO,oBAAoB,OAAO;AAE1D,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,EACF;AAGA,mBAAiB,qBAAqB,cAClC,gBACA;AAEJ,uBAAqB,gBAAgB;AACrC,kCAAgC,kBAAkB,kBAAkB;AAEpE,6BAA2B,kBAAkB;AAG7C,QAAM,kBAAkB,CAAC,OACtB,cAAc,EACd,IAAI,iBAAiB,SAAS;AAEjC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,SAAS,SAAS,oBAAoB,gBAAgB;AAE5D;AAAA,IACQ;AAAA,MACJ,CAAC,kBAAkB;AACjB,cAAM,cAAc,cAChB,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAI9D,iBAAS,aAAa;AAEtB,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS,WAAW,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5D,GAAG,CAAC,kBAAkB,QAAQ,CAAC;AAG/B,MAAI,cAAc,kBAAkB,MAAM,GAAG;AAC3C,UAAM,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA,EACtE;AAGA,MACE,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,OAAO,OACJ,cAAc,EACd,IAKC,iBAAiB,SAAS;AAAA,EAChC,CAAC,GACD;AACA,UAAM,OAAO;AAAA,EACf;AAEA;AAAC,EAAC,OAAO,kBAAkB,EAAE,SAAiB;AAAA,IAC5C;AAAA,IACA;AAAA,EACF;AAEA,MACE,iBAAiB,iCACjB,CAAC,YACD,UAAU,QAAQ,WAAW,GAC7B;AACA,UAAM,UAAU;AAAA;AAAA,MAEZ,gBAAgB,kBAAkB,UAAU,kBAAkB;AAAA;AAAA;AAAA,MAE9D,OAAO,cAAc,EAAE,IAAI,iBAAiB,SAAS,GAAG;AAAA;AAE5D,aAAS,MAAM,IAAI,EAAE,QAAQ,MAAM;AAEjC,eAAS,aAAa;AAAA,IACxB,CAAC;AAAA,EACH;AAGA,SAAO,CAAC,iBAAiB,sBACrB,SAAS,YAAY,MAAM,IAC3B;AACN;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useIsFetching.cjs b/build/modern/useIsFetching.cjs +index 28660e7d19489acc86f6a2f0c9b47e453ac66fae..2bed8ddef2f97adfb60c35aa83630259898e5e20 100644 +--- a/build/modern/useIsFetching.cjs ++++ b/build/modern/useIsFetching.cjs +@@ -35,12 +35,13 @@ __export(useIsFetching_exports, { + }); + module.exports = __toCommonJS(useIsFetching_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + function useIsFetching(filters, queryClient) { + const client = (0, import_QueryClientProvider.useQueryClient)(queryClient); + const queryCache = client.getQueryCache(); +- return React.useSyncExternalStore( ++ return (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => queryCache.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)), + [queryCache] +diff --git a/build/modern/useIsFetching.cjs.map b/build/modern/useIsFetching.cjs.map +index 5a58e86806e2919b9dcfbaf0cc3c32a4e23a5661..d3d112b618dc78caf24b36510852fdd647381c0a 100644 +--- a/build/modern/useIsFetching.cjs.map ++++ b/build/modern/useIsFetching.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,wBAA8B;AAE9B,iCAA+B;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAA8B;AAE9B,iCAA+B;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,aAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useIsFetching.js b/build/modern/useIsFetching.js +index acfc67a302d371b13b632cfdfcba1740ac6cfa22..90af8d148cbedb97df0b11b64fe84b4db973acd4 100644 +--- a/build/modern/useIsFetching.js ++++ b/build/modern/useIsFetching.js +@@ -2,12 +2,13 @@ + + // src/useIsFetching.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { notifyManager } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + function useIsFetching(filters, queryClient) { + const client = useQueryClient(queryClient); + const queryCache = client.getQueryCache(); +- return React.useSyncExternalStore( ++ return useSyncExternalStore( + React.useCallback( + (onStoreChange) => queryCache.subscribe(notifyManager.batchCalls(onStoreChange)), + [queryCache] +diff --git a/build/modern/useIsFetching.js.map b/build/modern/useIsFetching.js.map +index 9921ab6e20952d564197ef61fccc3ab1f4943bd0..4b13c50e8e70381758c583c3b8cfbd0180d13a04 100644 +--- a/build/modern/useIsFetching.js.map ++++ b/build/modern/useIsFetching.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,qBAAqB;AAE9B,SAAS,sBAAsB;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useIsFetching.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager } from '@tanstack/query-core'\n\nimport { useQueryClient } from './QueryClientProvider'\nimport type { QueryClient, QueryFilters } from '@tanstack/query-core'\n\nexport function useIsFetching(\n filters?: QueryFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n const queryCache = client.getQueryCache()\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n queryCache.subscribe(notifyManager.batchCalls(onStoreChange)),\n [queryCache],\n ),\n () => client.isFetching(filters),\n () => client.isFetching(filters),\n )\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,qBAAqB;AAE9B,SAAS,sBAAsB;AAGxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,aAAa,OAAO,cAAc;AAExC,SAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,WAAW,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC9D,CAAC,UAAU;AAAA,IACb;AAAA,IACA,MAAM,OAAO,WAAW,OAAO;AAAA,IAC/B,MAAM,OAAO,WAAW,OAAO;AAAA,EACjC;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useMutation.cjs b/build/modern/useMutation.cjs +index 175de467172e7c876d51141d22f151de482d2a43..826a83d5f08d22035d1f8bd31a0236299055dec3 100644 +--- a/build/modern/useMutation.cjs ++++ b/build/modern/useMutation.cjs +@@ -35,6 +35,7 @@ __export(useMutation_exports, { + }); + module.exports = __toCommonJS(useMutation_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + var import_utils = require("./utils.cjs"); +@@ -49,7 +50,7 @@ function useMutation(options, queryClient) { + React.useEffect(() => { + observer.setOptions(options); + }, [observer, options]); +- const result = React.useSyncExternalStore( ++ const result = (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => observer.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)), + [observer] +diff --git a/build/modern/useMutation.cjs.map b/build/modern/useMutation.cjs.map +index 2beaf7a697d67be63bb22ae4739b0db0eeede8f7..ffd27eb4f52319afc1afa4122c9982f6484591bd 100644 +--- a/build/modern/useMutation.cjs.map ++++ b/build/modern/useMutation.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,wBAAgD;AAChD,iCAA+B;AAC/B,mBAAuC;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,aAAS,2CAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,SAAe;AAAA,IACb;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,iBAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,aACP,+BAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAAgD;AAChD,iCAA+B;AAC/B,mBAAuC;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,aAAS,2CAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,aAAS;AAAA,IACP;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,iBAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,aACP,+BAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useMutation.js b/build/modern/useMutation.js +index 515a3b92ecf8c348ccc7f16de4f778301327e9c9..a135e33b89a5cf9ef8d1725a9aada6283052bed9 100644 +--- a/build/modern/useMutation.js ++++ b/build/modern/useMutation.js +@@ -2,6 +2,7 @@ + + // src/useMutation.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { MutationObserver, notifyManager } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + import { noop, shouldThrowError } from "./utils.js"; +@@ -16,7 +17,7 @@ function useMutation(options, queryClient) { + React.useEffect(() => { + observer.setOptions(options); + }, [observer, options]); +- const result = React.useSyncExternalStore( ++ const result = useSyncExternalStore( + React.useCallback( + (onStoreChange) => observer.subscribe(notifyManager.batchCalls(onStoreChange)), + [observer] +diff --git a/build/modern/useMutation.js.map b/build/modern/useMutation.js.map +index 0627ad75983fcc9d6cd9d66a20f7a935dd076ad4..03013010c6b9d825c2888d9ac03edc774e8b7965 100644 +--- a/build/modern/useMutation.js.map ++++ b/build/modern/useMutation.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,kBAAkB,qBAAqB;AAChD,SAAS,sBAAsB;AAC/B,SAAS,MAAM,wBAAwB;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,SAAS,eAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,SAAe;AAAA,IACb;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,IAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,SACP,iBAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutation.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { MutationObserver, notifyManager } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { noop, shouldThrowError } from './utils'\nimport type {\n UseMutateFunction,\n UseMutationOptions,\n UseMutationResult,\n} from './types'\nimport type { DefaultError, QueryClient } from '@tanstack/query-core'\n\n// HOOK\n\nexport function useMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions,\n queryClient?: QueryClient,\n): UseMutationResult {\n const client = useQueryClient(queryClient)\n\n const [observer] = React.useState(\n () =>\n new MutationObserver(\n client,\n options,\n ),\n )\n\n React.useEffect(() => {\n observer.setOptions(options)\n }, [observer, options])\n\n const result = useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n const mutate = React.useCallback<\n UseMutateFunction\n >(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop)\n },\n [observer],\n )\n\n if (\n result.error &&\n shouldThrowError(observer.options.throwOnError, [result.error])\n ) {\n throw result.error\n }\n\n return { ...result, mutate, mutateAsync: result.mutate }\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,kBAAkB,qBAAqB;AAChD,SAAS,sBAAsB;AAC/B,SAAS,MAAM,wBAAwB;AAUhC,SAAS,YAMd,SACA,aACwD;AACxD,QAAM,SAAS,eAAe,WAAW;AAEzC,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,EAAM,gBAAU,MAAM;AACpB,aAAS,WAAW,OAAO;AAAA,EAC7B,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,SAAS;AAAA,IACP;AAAA,MACJ,CAAC,kBACC,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAC5D,CAAC,QAAQ;AAAA,IACX;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,QAAM,SAAe;AAAA,IAGnB,CAAC,WAAW,kBAAkB;AAC5B,eAAS,OAAO,WAAW,aAAa,EAAE,MAAM,IAAI;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,MACE,OAAO,SACP,iBAAiB,SAAS,QAAQ,cAAc,CAAC,OAAO,KAAK,CAAC,GAC9D;AACA,UAAM,OAAO;AAAA,EACf;AAEA,SAAO,EAAE,GAAG,QAAQ,QAAQ,aAAa,OAAO,OAAO;AACzD;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useMutationState.cjs b/build/modern/useMutationState.cjs +index 0248bea1b0a0922589748a9338d85be66fc3468c..0bb6d8ac2eacb572b35c29429ef5d94edf33b7ad 100644 +--- a/build/modern/useMutationState.cjs ++++ b/build/modern/useMutationState.cjs +@@ -36,6 +36,7 @@ __export(useMutationState_exports, { + }); + module.exports = __toCommonJS(useMutationState_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + function useIsMutating(filters, queryClient) { +@@ -60,7 +61,7 @@ function useMutationState(options = {}, queryClient) { + React.useEffect(() => { + optionsRef.current = options; + }); +- return React.useSyncExternalStore( ++ return (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => mutationCache.subscribe(() => { + const nextResult = (0, import_query_core.replaceEqualDeep)( +diff --git a/build/modern/useMutationState.cjs.map b/build/modern/useMutationState.cjs.map +index 68b0a392336cba75982a1146353c1e14698fca14..6383002ae8e9b97a4390db3bcead0e1955925ac6 100644 +--- a/build/modern/useMutationState.cjs.map ++++ b/build/modern/useMutationState.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,YAAuB;AAEvB,wBAAgD;AAChD,iCAA+B;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,oBAAgB,2CAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,iBAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,0CAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,YAAuB;AACvB,kBAAqC;AAErC,wBAAgD;AAChD,iCAA+B;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,aAAS,2CAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,oBAAgB,2CAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,aAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,iBAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,0CAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useMutationState.js b/build/modern/useMutationState.js +index 0648af4cfd70499f3365abc8b63a06e06976f793..2345f0eecff02f33f0354832b94ce0fdfa31540e 100644 +--- a/build/modern/useMutationState.js ++++ b/build/modern/useMutationState.js +@@ -2,6 +2,7 @@ + + // src/useMutationState.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { notifyManager, replaceEqualDeep } from "@tanstack/query-core"; + import { useQueryClient } from "./QueryClientProvider.js"; + function useIsMutating(filters, queryClient) { +@@ -26,7 +27,7 @@ function useMutationState(options = {}, queryClient) { + React.useEffect(() => { + optionsRef.current = options; + }); +- return React.useSyncExternalStore( ++ return useSyncExternalStore( + React.useCallback( + (onStoreChange) => mutationCache.subscribe(() => { + const nextResult = replaceEqualDeep( +diff --git a/build/modern/useMutationState.js.map b/build/modern/useMutationState.js.map +index ae13415e7f9c31177b3ccd37a92ba91b10385705..aa4027b3c846be5f0f769339aee4ff1ac2c0de82 100644 +--- a/build/modern/useMutationState.js.map ++++ b/build/modern/useMutationState.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;AAGA,YAAY,WAAW;AAEvB,SAAS,eAAe,wBAAwB;AAChD,SAAS,sBAAsB;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,gBAAgB,eAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,SAAa;AAAA,IACL;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,aAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,wBAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useMutationState.ts"],"sourcesContent":["/* eslint-disable react-compiler/react-compiler */\n\n'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport { notifyManager, replaceEqualDeep } from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport type {\n Mutation,\n MutationCache,\n MutationFilters,\n MutationState,\n QueryClient,\n} from '@tanstack/query-core'\n\nexport function useIsMutating(\n filters?: MutationFilters,\n queryClient?: QueryClient,\n): number {\n const client = useQueryClient(queryClient)\n return useMutationState(\n { filters: { ...filters, status: 'pending' } },\n client,\n ).length\n}\n\ntype MutationStateOptions = {\n filters?: MutationFilters\n select?: (mutation: Mutation) => TResult\n}\n\nfunction getResult(\n mutationCache: MutationCache,\n options: MutationStateOptions,\n): Array {\n return mutationCache\n .findAll(options.filters)\n .map(\n (mutation): TResult =>\n (options.select ? options.select(mutation) : mutation.state) as TResult,\n )\n}\n\nexport function useMutationState(\n options: MutationStateOptions = {},\n queryClient?: QueryClient,\n): Array {\n const mutationCache = useQueryClient(queryClient).getMutationCache()\n const optionsRef = React.useRef(options)\n const result = React.useRef>(null)\n if (!result.current) {\n result.current = getResult(mutationCache, options)\n }\n\n React.useEffect(() => {\n optionsRef.current = options\n })\n\n return useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n mutationCache.subscribe(() => {\n const nextResult = replaceEqualDeep(\n result.current,\n getResult(mutationCache, optionsRef.current),\n )\n if (result.current !== nextResult) {\n result.current = nextResult\n notifyManager.schedule(onStoreChange)\n }\n }),\n [mutationCache],\n ),\n () => result.current,\n () => result.current,\n )!\n}\n"],"mappings":";;;AAGA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC,SAAS,eAAe,wBAAwB;AAChD,SAAS,sBAAsB;AASxB,SAAS,cACd,SACA,aACQ;AACR,QAAM,SAAS,eAAe,WAAW;AACzC,SAAO;AAAA,IACL,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,UAAU,EAAE;AAAA,IAC7C;AAAA,EACF,EAAE;AACJ;AAOA,SAAS,UACP,eACA,SACgB;AAChB,SAAO,cACJ,QAAQ,QAAQ,OAAO,EACvB;AAAA,IACC,CAAC,aACE,QAAQ,SAAS,QAAQ,OAAO,QAAQ,IAAI,SAAS;AAAA,EAC1D;AACJ;AAEO,SAAS,iBACd,UAAyC,CAAC,GAC1C,aACgB;AAChB,QAAM,gBAAgB,eAAe,WAAW,EAAE,iBAAiB;AACnE,QAAM,aAAmB,aAAO,OAAO;AACvC,QAAM,SAAe,aAAuB,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,UAAU,eAAe,OAAO;AAAA,EACnD;AAEA,EAAM,gBAAU,MAAM;AACpB,eAAW,UAAU;AAAA,EACvB,CAAC;AAED,SAAO;AAAA,IACC;AAAA,MACJ,CAAC,kBACC,cAAc,UAAU,MAAM;AAC5B,cAAM,aAAa;AAAA,UACjB,OAAO;AAAA,UACP,UAAU,eAAe,WAAW,OAAO;AAAA,QAC7C;AACA,YAAI,OAAO,YAAY,YAAY;AACjC,iBAAO,UAAU;AACjB,wBAAc,SAAS,aAAa;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,MACH,CAAC,aAAa;AAAA,IAChB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,EACf;AACF;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useQueries.cjs b/build/modern/useQueries.cjs +index a3be327942dfeb675da9da9308a4e21d7c29704c..91f094199c71a83c54198726eb18233b66f56171 100644 +--- a/build/modern/useQueries.cjs ++++ b/build/modern/useQueries.cjs +@@ -35,6 +35,7 @@ __export(useQueries_exports, { + }); + module.exports = __toCommonJS(useQueries_exports); + var React = __toESM(require("react"), 1); ++var import_shim = require("use-sync-external-store/shim/index.js"); + var import_query_core = require("@tanstack/query-core"); + var import_QueryClientProvider = require("./QueryClientProvider.cjs"); + var import_isRestoring = require("./isRestoring.cjs"); +@@ -75,7 +76,7 @@ function useQueries({ + defaultedQueries, + options.combine + ); +- React.useSyncExternalStore( ++ (0, import_shim.useSyncExternalStore)( + React.useCallback( + (onStoreChange) => isRestoring ? import_utils.noop : observer.subscribe(import_query_core.notifyManager.batchCalls(onStoreChange)), + [observer, isRestoring] +diff --git a/build/modern/useQueries.cjs.map b/build/modern/useQueries.cjs.map +index a6403e666c754b1bf351a8553556e6628c61ac30..5a4b7ef9d50310739f8b02562da0ad6dd676693b 100644 +--- a/build/modern/useQueries.cjs.map ++++ b/build/modern/useQueries.cjs.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AAEvB,wBAIO;AACP,iCAA+B;AAC/B,yBAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,sBAKO;AACP,mBAAqB;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,8CAAqB,KAAK;AAC1B,mEAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,4DAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBACC,cACI,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,cAC7D,+BAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,gCAAc,QAAQ,IAAI;AACpD,cAAI,+BAAc,MAAM,MAAM,GAAG;AAC/B,mBAAO,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,eAAW,2BAAU,QAAQ,WAAW,GAAG;AACzC,iBAAK,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,aACA,uCAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,mCAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AACvB,kBAAqC;AAErC,wBAIO;AACP,iCAA+B;AAC/B,yBAA+B;AAC/B,qCAA2C;AAC3C,gCAIO;AACP,sBAKO;AACP,mBAAqB;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,aAAS,2CAAe,WAAW;AACzC,QAAM,kBAAc,mCAAe;AACnC,QAAM,yBAAqB,2DAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,8CAAqB,KAAK;AAC1B,mEAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,4DAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF;AAAA,IACQ;AAAA,MACJ,CAAC,kBACC,cACI,oBACA,SAAS,UAAU,gCAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,cAC7D,+BAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,gCAAc,QAAQ,IAAI;AACpD,cAAI,+BAAc,MAAM,MAAM,GAAG;AAC/B,mBAAO,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,eAAW,2BAAU,QAAQ,WAAW,GAAG;AACzC,iBAAK,iCAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,aACA,uCAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,mCAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file +diff --git a/build/modern/useQueries.js b/build/modern/useQueries.js +index c09facb7f2f05a71a62c8543e4d9bf08ff18d718..52ba2a55518517b0b0d1d40a5a2dbb038ddc19e5 100644 +--- a/build/modern/useQueries.js ++++ b/build/modern/useQueries.js +@@ -2,6 +2,7 @@ + + // src/useQueries.ts + import * as React from "react"; ++import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; + import { + QueriesObserver, + QueryObserver, +@@ -55,7 +56,7 @@ function useQueries({ + defaultedQueries, + options.combine + ); +- React.useSyncExternalStore( ++ useSyncExternalStore( + React.useCallback( + (onStoreChange) => isRestoring ? noop : observer.subscribe(notifyManager.batchCalls(onStoreChange)), + [observer, isRestoring] +diff --git a/build/modern/useQueries.js.map b/build/modern/useQueries.js.map +index cce8620de6f08dc7b6dd927df034edc54ab0ea50..a4c9aad6ffdf06c8946073559447bae8e63d4761 100644 +--- a/build/modern/useQueries.js.map ++++ b/build/modern/useQueries.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AAEvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,yBAAqB,KAAK;AAC1B,oCAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,6BAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF,EAAM;AAAA,IACE;AAAA,MACJ,CAAC,kBACC,cACI,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,UAC7D,cAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,cAAc,QAAQ,IAAI;AACpD,UAAI,cAAc,MAAM,MAAM,GAAG;AAC/B,eAAO,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,WAAW,UAAU,QAAQ,WAAW,GAAG;AACzC,aAAK,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,SACA,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,mCAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file ++{"version":3,"sources":["../../src/useQueries.ts"],"sourcesContent":["'use client'\nimport * as React from 'react'\nimport { useSyncExternalStore } from 'use-sync-external-store/shim/index.js'\n\nimport {\n QueriesObserver,\n QueryObserver,\n notifyManager,\n} from '@tanstack/query-core'\nimport { useQueryClient } from './QueryClientProvider'\nimport { useIsRestoring } from './isRestoring'\nimport { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary,\n} from './errorBoundaryUtils'\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch,\n} from './suspense'\nimport { noop } from './utils'\nimport type {\n DefinedUseQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from './types'\nimport type {\n DefaultError,\n OmitKeyof,\n QueriesObserverOptions,\n QueriesPlaceholderDataFunction,\n QueryClient,\n QueryFunction,\n QueryKey,\n QueryObserverOptions,\n ThrowOnError,\n} from '@tanstack/query-core'\n\n// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.\n// `placeholderData` function always gets undefined passed\ntype UseQueryOptionsForUseQueries<\n TQueryFnData = unknown,\n TError = DefaultError,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n> = OmitKeyof<\n UseQueryOptions,\n 'placeholderData'\n> & {\n placeholderData?: TQueryFnData | QueriesPlaceholderDataFunction\n}\n\n// Avoid TS depth-limit error in case of large array literal\ntype MAXIMUM_DEPTH = 20\n\n// Widen the type of the symbol to enable type inference even if skipToken is not immutable.\ntype SkipTokenForUseQueries = symbol\n\ntype GetUseQueryOptionsForUseQueries =\n // Part 1: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData }\n T extends {\n queryFnData: infer TQueryFnData\n error?: infer TError\n data: infer TData\n }\n ? UseQueryOptionsForUseQueries\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : T extends { data: infer TData; error?: infer TError }\n ? UseQueryOptionsForUseQueries\n : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]\n T extends [infer TQueryFnData, infer TError, infer TData]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData, infer TError]\n ? UseQueryOptionsForUseQueries\n : T extends [infer TQueryFnData]\n ? UseQueryOptionsForUseQueries\n : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? UseQueryOptionsForUseQueries<\n TQueryFnData,\n unknown extends TError ? DefaultError : TError,\n unknown extends TData ? TQueryFnData : TData,\n TQueryKey\n >\n : // Fallback\n UseQueryOptionsForUseQueries\n\n// A defined initialData setting should return a DefinedUseQueryResult rather than UseQueryResult\ntype GetDefinedOrUndefinedQueryResult = T extends {\n initialData?: infer TInitialData\n}\n ? unknown extends TInitialData\n ? UseQueryResult\n : TInitialData extends TData\n ? DefinedUseQueryResult\n : TInitialData extends () => infer TInitialDataResult\n ? unknown extends TInitialDataResult\n ? UseQueryResult\n : TInitialDataResult extends TData\n ? DefinedUseQueryResult\n : UseQueryResult\n : UseQueryResult\n : UseQueryResult\n\ntype GetUseQueryResult =\n // Part 1: responsible for mapping explicit type parameter to function result, if object\n T extends { queryFnData: any; error?: infer TError; data: infer TData }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { queryFnData: infer TQueryFnData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : T extends { data: infer TData; error?: infer TError }\n ? GetDefinedOrUndefinedQueryResult\n : // Part 2: responsible for mapping explicit type parameter to function result, if tuple\n T extends [any, infer TError, infer TData]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData, infer TError]\n ? GetDefinedOrUndefinedQueryResult\n : T extends [infer TQueryFnData]\n ? GetDefinedOrUndefinedQueryResult\n : // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided\n T extends {\n queryFn?:\n | QueryFunction\n | SkipTokenForUseQueries\n select?: (data: any) => infer TData\n throwOnError?: ThrowOnError\n }\n ? GetDefinedOrUndefinedQueryResult<\n T,\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n : // Fallback\n UseQueryResult\n\n/**\n * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param\n */\nexport type QueriesOptions<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryOptionsForUseQueries]\n : T extends [infer Head, ...infer Tails]\n ? QueriesOptions<\n [...Tails],\n [...TResults, GetUseQueryOptionsForUseQueries],\n [...TDepth, 1]\n >\n : ReadonlyArray extends T\n ? T\n : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!\n // use this to infer the param types in the case of Array.map() argument\n T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n infer TQueryKey\n >\n >\n ? Array<\n UseQueryOptionsForUseQueries<\n TQueryFnData,\n TError,\n TData,\n TQueryKey\n >\n >\n : // Fallback\n Array\n\n/**\n * QueriesResults reducer recursively maps type param to results\n */\nexport type QueriesResults<\n T extends Array,\n TResults extends Array = [],\n TDepth extends ReadonlyArray = [],\n> = TDepth['length'] extends MAXIMUM_DEPTH\n ? Array\n : T extends []\n ? []\n : T extends [infer Head]\n ? [...TResults, GetUseQueryResult]\n : T extends [infer Head, ...infer Tails]\n ? QueriesResults<\n [...Tails],\n [...TResults, GetUseQueryResult],\n [...TDepth, 1]\n >\n : T extends Array<\n UseQueryOptionsForUseQueries<\n infer TQueryFnData,\n infer TError,\n infer TData,\n any\n >\n >\n ? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results\n Array<\n UseQueryResult<\n unknown extends TData ? TQueryFnData : TData,\n unknown extends TError ? DefaultError : TError\n >\n >\n : // Fallback\n Array\n\nexport function useQueries<\n T extends Array,\n TCombinedResult = QueriesResults,\n>(\n {\n queries,\n ...options\n }: {\n queries: readonly [...QueriesOptions]\n combine?: (result: QueriesResults) => TCombinedResult\n },\n queryClient?: QueryClient,\n): TCombinedResult {\n const client = useQueryClient(queryClient)\n const isRestoring = useIsRestoring()\n const errorResetBoundary = useQueryErrorResetBoundary()\n\n const defaultedQueries = React.useMemo(\n () =>\n queries.map((opts) => {\n const defaultedOptions = client.defaultQueryOptions(\n opts as QueryObserverOptions,\n )\n\n // Make sure the results are already in fetching state before subscribing or updating options\n defaultedOptions._optimisticResults = isRestoring\n ? 'isRestoring'\n : 'optimistic'\n\n return defaultedOptions\n }),\n [queries, client, isRestoring],\n )\n\n defaultedQueries.forEach((query) => {\n ensureSuspenseTimers(query)\n ensurePreventErrorBoundaryRetry(query, errorResetBoundary)\n })\n\n useClearResetErrorBoundary(errorResetBoundary)\n\n const [observer] = React.useState(\n () =>\n new QueriesObserver(\n client,\n defaultedQueries,\n options as QueriesObserverOptions,\n ),\n )\n\n const [optimisticResult, getCombinedResult, trackResult] =\n observer.getOptimisticResult(\n defaultedQueries,\n (options as QueriesObserverOptions).combine,\n )\n\n useSyncExternalStore(\n React.useCallback(\n (onStoreChange) =>\n isRestoring\n ? noop\n : observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer, isRestoring],\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult(),\n )\n\n React.useEffect(() => {\n // Do not notify on updates because of changes in the options because\n // these changes should already be reflected in the optimistic result.\n observer.setQueries(\n defaultedQueries,\n options as QueriesObserverOptions,\n {\n listeners: false,\n },\n )\n }, [defaultedQueries, options, observer])\n\n const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>\n shouldSuspend(defaultedQueries[index], result),\n )\n\n const suspensePromises = shouldAtLeastOneSuspend\n ? optimisticResult.flatMap((result, index) => {\n const opts = defaultedQueries[index]\n\n if (opts) {\n const queryObserver = new QueryObserver(client, opts)\n if (shouldSuspend(opts, result)) {\n return fetchOptimistic(opts, queryObserver, errorResetBoundary)\n } else if (willFetch(result, isRestoring)) {\n void fetchOptimistic(opts, queryObserver, errorResetBoundary)\n }\n }\n return []\n })\n : []\n\n if (suspensePromises.length > 0) {\n throw Promise.all(suspensePromises)\n }\n const firstSingleResultWhichShouldThrow = optimisticResult.find(\n (result, index) => {\n const query = defaultedQueries[index]\n return (\n query &&\n getHasError({\n result,\n errorResetBoundary,\n throwOnError: query.throwOnError,\n query: client.getQueryCache().get(query.queryHash),\n })\n )\n },\n )\n\n if (firstSingleResultWhichShouldThrow?.error) {\n throw firstSingleResultWhichShouldThrow.error\n }\n\n return getCombinedResult(trackResult())\n}\n"],"mappings":";;;AACA,YAAY,WAAW;AACvB,SAAS,4BAA4B;AAErC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AAyMd,SAAS,WAId;AAAA,EACE;AAAA,EACA,GAAG;AACL,GAIA,aACiB;AACjB,QAAM,SAAS,eAAe,WAAW;AACzC,QAAM,cAAc,eAAe;AACnC,QAAM,qBAAqB,2BAA2B;AAEtD,QAAM,mBAAyB;AAAA,IAC7B,MACE,QAAQ,IAAI,CAAC,SAAS;AACpB,YAAM,mBAAmB,OAAO;AAAA,QAC9B;AAAA,MACF;AAGA,uBAAiB,qBAAqB,cAClC,gBACA;AAEJ,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,SAAS,QAAQ,WAAW;AAAA,EAC/B;AAEA,mBAAiB,QAAQ,CAAC,UAAU;AAClC,yBAAqB,KAAK;AAC1B,oCAAgC,OAAO,kBAAkB;AAAA,EAC3D,CAAC;AAED,6BAA2B,kBAAkB;AAE7C,QAAM,CAAC,QAAQ,IAAU;AAAA,IACvB,MACE,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AAEA,QAAM,CAAC,kBAAkB,mBAAmB,WAAW,IACrD,SAAS;AAAA,IACP;AAAA,IACC,QAAoD;AAAA,EACvD;AAEF;AAAA,IACQ;AAAA,MACJ,CAAC,kBACC,cACI,OACA,SAAS,UAAU,cAAc,WAAW,aAAa,CAAC;AAAA,MAChE,CAAC,UAAU,WAAW;AAAA,IACxB;AAAA,IACA,MAAM,SAAS,iBAAiB;AAAA,IAChC,MAAM,SAAS,iBAAiB;AAAA,EAClC;AAEA,EAAM,gBAAU,MAAM;AAGpB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,QACE,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF,GAAG,CAAC,kBAAkB,SAAS,QAAQ,CAAC;AAExC,QAAM,0BAA0B,iBAAiB;AAAA,IAAK,CAAC,QAAQ,UAC7D,cAAc,iBAAiB,KAAK,GAAG,MAAM;AAAA,EAC/C;AAEA,QAAM,mBAAmB,0BACrB,iBAAiB,QAAQ,CAAC,QAAQ,UAAU;AAC1C,UAAM,OAAO,iBAAiB,KAAK;AAEnC,QAAI,MAAM;AACR,YAAM,gBAAgB,IAAI,cAAc,QAAQ,IAAI;AACpD,UAAI,cAAc,MAAM,MAAM,GAAG;AAC/B,eAAO,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAChE,WAAW,UAAU,QAAQ,WAAW,GAAG;AACzC,aAAK,gBAAgB,MAAM,eAAe,kBAAkB;AAAA,MAC9D;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV,CAAC,IACD,CAAC;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,IAAI,gBAAgB;AAAA,EACpC;AACA,QAAM,oCAAoC,iBAAiB;AAAA,IACzD,CAAC,QAAQ,UAAU;AACjB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,SACA,YAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,OAAO,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS;AAAA,MACnD,CAAC;AAAA,IAEL;AAAA,EACF;AAEA,MAAI,mCAAmC,OAAO;AAC5C,UAAM,kCAAkC;AAAA,EAC1C;AAEA,SAAO,kBAAkB,YAAY,CAAC;AACxC;","names":[]} +\ No newline at end of file +diff --git a/package.json b/package.json +index 822a6ead845585e68f6b6b7942b72718c76cd8d5..cebbaf6792416d47f6aef82d1d1a4a61a8053af7 100644 +--- a/package.json ++++ b/package.json +@@ -47,6 +47,7 @@ + "devDependencies": { + "@types/react": "npm:types-react@rc", + "@types/react-dom": "npm:types-react-dom@rc", ++ "@types/use-sync-external-store": "^0.0.6", + "@vitejs/plugin-react": "^4.3.1", + "eslint-plugin-react-compiler": "0.0.0-experimental-f8a5409-20240829", + "react": "19.0.0-rc-4c2e457c7c-20240522", +diff --git a/src/useBaseQuery.ts b/src/useBaseQuery.ts +index bcbf700ef73cd0b74753b4efa0532de77976d891..6f9ef2e36d13690535d58a1310785300896fe511 100644 +--- a/src/useBaseQuery.ts ++++ b/src/useBaseQuery.ts +@@ -1,5 +1,6 @@ + 'use client' + import * as React from 'react' ++import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js' + + import { isServer, notifyManager } from '@tanstack/query-core' + import { useQueryClient } from './QueryClientProvider' +@@ -84,7 +85,7 @@ export function useBaseQuery< + + const result = observer.getOptimisticResult(defaultedOptions) + +- React.useSyncExternalStore( ++ useSyncExternalStore( + React.useCallback( + (onStoreChange) => { + const unsubscribe = isRestoring +diff --git a/src/useIsFetching.ts b/src/useIsFetching.ts +index a6252912f22e0504e3212bd1aee683b4930db771..5ba06d618eda0a71cbc0d49387e01f035f15863a 100644 +--- a/src/useIsFetching.ts ++++ b/src/useIsFetching.ts +@@ -1,5 +1,7 @@ + 'use client' + import * as React from 'react' ++import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js' ++ + import { notifyManager } from '@tanstack/query-core' + + import { useQueryClient } from './QueryClientProvider' +@@ -12,7 +14,7 @@ export function useIsFetching( + const client = useQueryClient(queryClient) + const queryCache = client.getQueryCache() + +- return React.useSyncExternalStore( ++ return useSyncExternalStore( + React.useCallback( + (onStoreChange) => + queryCache.subscribe(notifyManager.batchCalls(onStoreChange)), +diff --git a/src/useMutation copy.ts b/src/useMutation copy.ts +new file mode 100644 +index 0000000000000000000000000000000000000000..90209500b3d42c53639540fdd9bc0aa47d79b005 +--- /dev/null ++++ b/src/useMutation copy.ts +@@ -0,0 +1,67 @@ ++'use client' ++import * as React from 'react' ++import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js' ++ ++import { MutationObserver, notifyManager } from '@tanstack/query-core' ++import { useQueryClient } from './QueryClientProvider' ++import { noop, shouldThrowError } from './utils' ++import type { ++ UseMutateFunction, ++ UseMutationOptions, ++ UseMutationResult, ++} from './types' ++import type { DefaultError, QueryClient } from '@tanstack/query-core' ++ ++// HOOK ++ ++export function useMutation< ++ TData = unknown, ++ TError = DefaultError, ++ TVariables = void, ++ TContext = unknown, ++>( ++ options: UseMutationOptions, ++ queryClient?: QueryClient, ++): UseMutationResult { ++ const client = useQueryClient(queryClient) ++ ++ const [observer] = React.useState( ++ () => ++ new MutationObserver( ++ client, ++ options, ++ ), ++ ) ++ ++ React.useEffect(() => { ++ observer.setOptions(options) ++ }, [observer, options]) ++ ++ const result = useSyncExternalStore( ++ React.useCallback( ++ (onStoreChange) => ++ observer.subscribe(notifyManager.batchCalls(onStoreChange)), ++ [observer], ++ ), ++ () => observer.getCurrentResult(), ++ () => observer.getCurrentResult(), ++ ) ++ ++ const mutate = React.useCallback< ++ UseMutateFunction ++ >( ++ (variables, mutateOptions) => { ++ observer.mutate(variables, mutateOptions).catch(noop) ++ }, ++ [observer], ++ ) ++ ++ if ( ++ result.error && ++ shouldThrowError(observer.options.throwOnError, [result.error]) ++ ) { ++ throw result.error ++ } ++ ++ return { ...result, mutate, mutateAsync: result.mutate } ++} +diff --git a/src/useMutation.ts b/src/useMutation.ts +deleted file mode 100644 +index 34edd450a2660473396e0c5acd1e3d550c34c43a..0000000000000000000000000000000000000000 +--- a/src/useMutation.ts ++++ /dev/null +@@ -1,65 +0,0 @@ +-'use client' +-import * as React from 'react' +-import { MutationObserver, notifyManager } from '@tanstack/query-core' +-import { useQueryClient } from './QueryClientProvider' +-import { noop, shouldThrowError } from './utils' +-import type { +- UseMutateFunction, +- UseMutationOptions, +- UseMutationResult, +-} from './types' +-import type { DefaultError, QueryClient } from '@tanstack/query-core' +- +-// HOOK +- +-export function useMutation< +- TData = unknown, +- TError = DefaultError, +- TVariables = void, +- TContext = unknown, +->( +- options: UseMutationOptions, +- queryClient?: QueryClient, +-): UseMutationResult { +- const client = useQueryClient(queryClient) +- +- const [observer] = React.useState( +- () => +- new MutationObserver( +- client, +- options, +- ), +- ) +- +- React.useEffect(() => { +- observer.setOptions(options) +- }, [observer, options]) +- +- const result = React.useSyncExternalStore( +- React.useCallback( +- (onStoreChange) => +- observer.subscribe(notifyManager.batchCalls(onStoreChange)), +- [observer], +- ), +- () => observer.getCurrentResult(), +- () => observer.getCurrentResult(), +- ) +- +- const mutate = React.useCallback< +- UseMutateFunction +- >( +- (variables, mutateOptions) => { +- observer.mutate(variables, mutateOptions).catch(noop) +- }, +- [observer], +- ) +- +- if ( +- result.error && +- shouldThrowError(observer.options.throwOnError, [result.error]) +- ) { +- throw result.error +- } +- +- return { ...result, mutate, mutateAsync: result.mutate } +-} +diff --git a/src/useMutationState.ts b/src/useMutationState.ts +index d962bf085d9dc30ba75fcc8fa6dde4e402fa41e7..3834135e17514534ce30bc27121f64b8638f3534 100644 +--- a/src/useMutationState.ts ++++ b/src/useMutationState.ts +@@ -2,6 +2,7 @@ + + 'use client' + import * as React from 'react' ++import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js' + + import { notifyManager, replaceEqualDeep } from '@tanstack/query-core' + import { useQueryClient } from './QueryClientProvider' +@@ -56,7 +57,7 @@ export function useMutationState( + optionsRef.current = options + }) + +- return React.useSyncExternalStore( ++ return useSyncExternalStore( + React.useCallback( + (onStoreChange) => + mutationCache.subscribe(() => { +diff --git a/src/useQueries.ts b/src/useQueries.ts +index 90ef2e32ad0d2267b2f3266cc5dc078ff9786e3f..505ce2e3312c67074a57a460cbda89c145d64de5 100644 +--- a/src/useQueries.ts ++++ b/src/useQueries.ts +@@ -1,5 +1,6 @@ + 'use client' + import * as React from 'react' ++import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js' + + import { + QueriesObserver, +@@ -277,7 +278,7 @@ export function useQueries< + (options as QueriesObserverOptions).combine, + ) + +- React.useSyncExternalStore( ++ useSyncExternalStore( + React.useCallback( + (onStoreChange) => + isRestoring diff --git a/apps/meteor/app/livechat/client/lib/stream/queueManager.ts b/apps/meteor/app/livechat/client/lib/stream/queueManager.ts index c6a671e2883d..4ebf49d55684 100644 --- a/apps/meteor/app/livechat/client/lib/stream/queueManager.ts +++ b/apps/meteor/app/livechat/client/lib/stream/queueManager.ts @@ -29,14 +29,14 @@ const events = { }; const invalidateRoomQueries = async (rid: string) => { - await queryClient.invalidateQueries(['rooms', { reference: rid, type: 'l' }]); - queryClient.removeQueries(['rooms', rid]); - queryClient.removeQueries(['/v1/rooms.info', rid]); + await queryClient.invalidateQueries({ queryKey: ['rooms', { reference: rid, type: 'l' }] }); + queryClient.removeQueries({ queryKey: ['rooms', rid] }); + queryClient.removeQueries({ queryKey: ['/v1/rooms.info', rid] }); }; const removeInquiry = async (inquiry: ILivechatInquiryRecord) => { LivechatInquiry.remove(inquiry._id); - return queryClient.invalidateQueries(['rooms', { reference: inquiry.rid, type: 'l' }]); + return queryClient.invalidateQueries({ queryKey: ['rooms', { reference: inquiry.rid, type: 'l' }] }); }; const getInquiriesFromAPI = async () => { diff --git a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useVoipItemsSection.tsx b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useVoipItemsSection.tsx index 1ee34d14c8d5..9a2584869b13 100644 --- a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useVoipItemsSection.tsx +++ b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useVoipItemsSection.tsx @@ -40,12 +40,12 @@ export const useVoipItemsSection = (): { items: GenericMenuItemProps[] } | undef return t(clientError.message); } - if (!isReady || toggleVoip.isLoading) { + if (!isReady || toggleVoip.isPending) { return t('Loading'); } return ''; - }, [clientError, isReady, toggleVoip.isLoading, t]); + }, [clientError, isReady, toggleVoip.isPending, t]); return useMemo(() => { if (!isEnabled) { @@ -57,7 +57,7 @@ export const useVoipItemsSection = (): { items: GenericMenuItemProps[] } | undef { id: 'toggle-voip', icon: isRegistered ? 'phone-disabled' : 'phone', - disabled: !isReady || toggleVoip.isLoading, + disabled: !isReady || toggleVoip.isPending, onClick: () => toggleVoip.mutate(), content: ( diff --git a/apps/meteor/client/apps/gameCenter/GameCenter.tsx b/apps/meteor/client/apps/gameCenter/GameCenter.tsx index 768a9d9ec81e..b6112bf86937 100644 --- a/apps/meteor/client/apps/gameCenter/GameCenter.tsx +++ b/apps/meteor/client/apps/gameCenter/GameCenter.tsx @@ -36,7 +36,7 @@ const GameCenter = (): ReactElement => { handleClose={handleClose} handleOpenGame={setOpenedGame} games={result.data} - isLoading={result.isLoading} + isLoading={result.isPending} /> )} diff --git a/apps/meteor/client/apps/gameCenter/hooks/useExternalComponentsQuery.ts b/apps/meteor/client/apps/gameCenter/hooks/useExternalComponentsQuery.ts index 7089257a322a..ab09322aea3a 100644 --- a/apps/meteor/client/apps/gameCenter/hooks/useExternalComponentsQuery.ts +++ b/apps/meteor/client/apps/gameCenter/hooks/useExternalComponentsQuery.ts @@ -3,13 +3,13 @@ import { useQuery } from '@tanstack/react-query'; export const useExternalComponentsQuery = () => { const getExternalComponents = useEndpoint('GET', '/apps/externalComponents'); - return useQuery( - ['apps/external-components'], - async () => { + return useQuery({ + queryKey: ['apps/external-components'], + + queryFn: async () => { return (await getExternalComponents()).externalComponents; }, - { - staleTime: 10_000, - }, - ); + + staleTime: 10_000, + }); }; diff --git a/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx b/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx index cf633206cc1d..e7bdd852a67d 100644 --- a/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx +++ b/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx @@ -245,7 +245,7 @@ const CreateDiscussion = ({ onClose, defaultParentRoom, parentMessageId, nameSug - diff --git a/apps/meteor/client/components/CreateDiscussion/DefaultParentRoomField.tsx b/apps/meteor/client/components/CreateDiscussion/DefaultParentRoomField.tsx index cb3816f17abe..fd012f7c5f8a 100644 --- a/apps/meteor/client/components/CreateDiscussion/DefaultParentRoomField.tsx +++ b/apps/meteor/client/components/CreateDiscussion/DefaultParentRoomField.tsx @@ -18,11 +18,13 @@ const DefaultParentRoomField = ({ defaultParentRoom }: { defaultParentRoom: stri const roomsInfoEndpoint = useEndpoint('GET', '/v1/rooms.info'); - const { data, isLoading, isError } = useQuery(['defaultParentRoomInfo', query], async () => roomsInfoEndpoint(query), { + const { data, isPending, isError } = useQuery({ + queryKey: ['defaultParentRoomInfo', query], + queryFn: async () => roomsInfoEndpoint(query), refetchOnWindowFocus: false, }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/components/Omnichannel/Tags.tsx b/apps/meteor/client/components/Omnichannel/Tags.tsx index 85d7f416037c..1e5732fb9c2f 100644 --- a/apps/meteor/client/components/Omnichannel/Tags.tsx +++ b/apps/meteor/client/components/Omnichannel/Tags.tsx @@ -20,7 +20,7 @@ type TagsProps = { const Tags = ({ tags = [], handler, error, tagRequired, department }: TagsProps): ReactElement => { const { t } = useTranslation(); - const { data: tagsResult, isInitialLoading } = useLivechatTags({ + const { data: tagsResult, isLoading } = useLivechatTags({ department, viewAll: !department, }); @@ -60,7 +60,7 @@ const Tags = ({ tags = [], handler, error, tagRequired, department }: TagsProps) handleTagValue(''); }); - if (isInitialLoading) { + if (isLoading) { return ; } diff --git a/apps/meteor/client/components/Omnichannel/hooks/useLivechatTags.ts b/apps/meteor/client/components/Omnichannel/hooks/useLivechatTags.ts index ce5704b66482..1b4aca036232 100644 --- a/apps/meteor/client/components/Omnichannel/hooks/useLivechatTags.ts +++ b/apps/meteor/client/components/Omnichannel/hooks/useLivechatTags.ts @@ -14,16 +14,16 @@ export const useLivechatTags = (options: Props) => { const { isEnterprise } = useOmnichannel(); const { department, text, viewAll } = options; - return useQuery( - ['/v1/livechat/tags', text, department], - () => + return useQuery({ + queryKey: ['/v1/livechat/tags', text, department], + + queryFn: () => getTags({ text: text || '', ...(department && { department }), viewAll: viewAll ? 'true' : 'false', }), - { - enabled: isEnterprise, - }, - ); + + enabled: isEnterprise, + }); }; diff --git a/apps/meteor/client/components/Omnichannel/modals/CloseChatModalData.tsx b/apps/meteor/client/components/Omnichannel/modals/CloseChatModalData.tsx index 867c992c8896..c1c6bb5e2446 100644 --- a/apps/meteor/client/components/Omnichannel/modals/CloseChatModalData.tsx +++ b/apps/meteor/client/components/Omnichannel/modals/CloseChatModalData.tsx @@ -21,9 +21,12 @@ const CloseChatModalData = ({ ) => Promise; }) => { const getDepartment = useEndpoint('GET', '/v1/livechat/department/:_id', { _id: departmentId }); - const { data, isLoading } = useQuery(['/v1/livechat/department/:_id', departmentId], () => getDepartment({})); + const { data, isPending } = useQuery({ + queryKey: ['/v1/livechat/department/:_id', departmentId], + queryFn: () => getDepartment({}), + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/components/RoomAutoComplete/RoomAutoComplete.tsx b/apps/meteor/client/components/RoomAutoComplete/RoomAutoComplete.tsx index 152fc6f9b7fe..66e30775ed79 100644 --- a/apps/meteor/client/components/RoomAutoComplete/RoomAutoComplete.tsx +++ b/apps/meteor/client/components/RoomAutoComplete/RoomAutoComplete.tsx @@ -3,7 +3,7 @@ import { AutoComplete, Option, Box } from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { RoomAvatar } from '@rocket.chat/ui-avatar'; import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { ComponentProps, Dispatch, ReactElement, SetStateAction } from 'react'; import { memo, useMemo, useState } from 'react'; @@ -37,13 +37,11 @@ const RoomAutoComplete = ({ value, onChange, scope = 'regular', renderRoomIcon, const filterDebounced = useDebouncedValue(filter, 300); const roomsAutoCompleteEndpoint = useEndpoint('GET', ROOM_AUTOCOMPLETE_PARAMS[scope].endpoint); - const result = useQuery( - [ROOM_AUTOCOMPLETE_PARAMS[scope].key, filterDebounced], - () => roomsAutoCompleteEndpoint(generateQuery(filterDebounced)), - { - keepPreviousData: true, - }, - ); + const result = useQuery({ + queryKey: [ROOM_AUTOCOMPLETE_PARAMS[scope].key, filterDebounced], + queryFn: () => roomsAutoCompleteEndpoint(generateQuery(filterDebounced)), + placeholderData: keepPreviousData, + }); const options = useMemo( () => diff --git a/apps/meteor/client/components/RoomAutoCompleteMultiple/RoomAutoCompleteMultiple.tsx b/apps/meteor/client/components/RoomAutoCompleteMultiple/RoomAutoCompleteMultiple.tsx index 18c911402810..87ad4714cc00 100644 --- a/apps/meteor/client/components/RoomAutoCompleteMultiple/RoomAutoCompleteMultiple.tsx +++ b/apps/meteor/client/components/RoomAutoCompleteMultiple/RoomAutoCompleteMultiple.tsx @@ -2,7 +2,7 @@ import { AutoComplete, Option, Chip, Box, Skeleton } from '@rocket.chat/fuselage import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { RoomAvatar } from '@rocket.chat/ui-avatar'; import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { ReactElement, ComponentProps } from 'react'; import { memo, useMemo, useState } from 'react'; @@ -21,8 +21,10 @@ const RoomAutoCompleteMultiple = ({ value, onChange, ...props }: RoomAutoComplet const filterDebounced = useDebouncedValue(filter, 300); const autocomplete = useEndpoint('GET', '/v1/rooms.autocomplete.channelAndPrivate'); - const result = useQuery(['rooms.autocomplete.channelAndPrivate', filterDebounced], () => autocomplete(generateQuery(filterDebounced)), { - keepPreviousData: true, + const result = useQuery({ + queryKey: ['rooms.autocomplete.channelAndPrivate', filterDebounced], + queryFn: () => autocomplete(generateQuery(filterDebounced)), + placeholderData: keepPreviousData, }); const options = useMemo( @@ -36,7 +38,7 @@ const RoomAutoCompleteMultiple = ({ value, onChange, ...props }: RoomAutoComplet [result.data?.items, result.isSuccess], ); - if (result.isLoading) { + if (result.isPending) { return ; } diff --git a/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx b/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx index 4ffb92ba2a51..d2d4a4774785 100644 --- a/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx +++ b/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx @@ -19,7 +19,10 @@ const UserAutoCompleteMultiple = ({ onChange, ...props }: UserAutoCompleteMultip const [filter, setFilter] = useState(''); const debouncedFilter = useDebouncedValue(filter, 1000); const usersAutoCompleteEndpoint = useEndpoint('GET', '/v1/users.autocomplete'); - const { data } = useQuery(['usersAutoComplete', debouncedFilter], async () => usersAutoCompleteEndpoint(query(debouncedFilter))); + const { data } = useQuery({ + queryKey: ['usersAutoComplete', debouncedFilter], + queryFn: async () => usersAutoCompleteEndpoint(query(debouncedFilter)), + }); const options = useMemo(() => data?.items.map((user) => ({ value: user.username, label: user.name })) || [], [data]); diff --git a/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated.tsx b/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated.tsx index 80bb67f12d66..6547fa02b9c9 100644 --- a/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated.tsx +++ b/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated.tsx @@ -2,7 +2,7 @@ import { MultiSelectFiltered, Icon, Box, Chip } from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { UserAvatar } from '@rocket.chat/ui-avatar'; import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { ReactElement, AllHTMLAttributes } from 'react'; import { memo, useState, useCallback, useMemo } from 'react'; @@ -38,9 +38,10 @@ const UserAutoCompleteMultipleFederated = ({ const debouncedFilter = useDebouncedValue(filter, 500); const getUsers = useEndpoint('GET', '/v1/users.autocomplete'); - const { data } = useQuery( - ['users.autocomplete', debouncedFilter], - async () => { + const { data } = useQuery({ + queryKey: ['users.autocomplete', debouncedFilter], + + queryFn: async () => { const users = await getUsers({ selector: JSON.stringify({ term: debouncedFilter }) }); const options = users.items.map((item): [string, UserAutoCompleteOptionType] => [item.username, item]); @@ -52,8 +53,9 @@ const UserAutoCompleteMultipleFederated = ({ return options; }, - { keepPreviousData: true }, - ); + + placeholderData: keepPreviousData, + }); const options = useMemo(() => data || [], [data]); diff --git a/apps/meteor/client/components/message/MessageToolbarHolder.tsx b/apps/meteor/client/components/message/MessageToolbarHolder.tsx index e85c67096c81..e1b65b3d0dd7 100644 --- a/apps/meteor/client/components/message/MessageToolbarHolder.tsx +++ b/apps/meteor/client/components/message/MessageToolbarHolder.tsx @@ -22,9 +22,10 @@ const MessageToolbarHolder = ({ message, context }: MessageToolbarHolderProps): const showToolbar = isVisible || isToolbarMenuOpen; - const depsQueryResult = useQuery( - ['toolbox', message._id, context], - async () => { + const depsQueryResult = useQuery({ + queryKey: ['toolbox', message._id, context], + + queryFn: async () => { const room = await chat?.data.findRoom(); const subscription = await chat?.data.findSubscription(); return { @@ -32,10 +33,9 @@ const MessageToolbarHolder = ({ message, context }: MessageToolbarHolderProps): subscription, }; }, - { - enabled: showToolbar, - }, - ); + + enabled: showToolbar, + }); return ( diff --git a/apps/meteor/client/components/message/content/attachments/default/ActionAttachmentButton.tsx b/apps/meteor/client/components/message/content/attachments/default/ActionAttachmentButton.tsx index 8491b2964f23..d0eddb046bce 100644 --- a/apps/meteor/client/components/message/content/attachments/default/ActionAttachmentButton.tsx +++ b/apps/meteor/client/components/message/content/attachments/default/ActionAttachmentButton.tsx @@ -28,7 +28,7 @@ const ActionAttachmentButton = ({ children, processingType, msg, mid }: ActionAt small value={msg} id={mid} - disabled={performActionMutation.isLoading} + disabled={performActionMutation.isPending} onClick={(event): void => { event.preventDefault(); diff --git a/apps/meteor/client/components/message/content/attachments/default/hooks/usePerformActionMutation.ts b/apps/meteor/client/components/message/content/attachments/default/hooks/usePerformActionMutation.ts index 82a757ae7187..807aa2727b3e 100644 --- a/apps/meteor/client/components/message/content/attachments/default/hooks/usePerformActionMutation.ts +++ b/apps/meteor/client/components/message/content/attachments/default/hooks/usePerformActionMutation.ts @@ -17,26 +17,30 @@ export const usePerformActionMutation = ( ): UseMutationResult => { const chat = useChat(); - return useMutation(async ({ processingType, msg, mid }) => { - if (!chat) { - return; - } - - switch (processingType) { - case 'sendMessage': - if (!msg) return; - await chat.flows.sendMessage({ text: msg }); + return useMutation({ + mutationFn: async ({ processingType, msg, mid }) => { + if (!chat) { return; - - case 'respondWithMessage': - if (!msg) return; - await chat.composer?.replyWith(msg); - return; - - case 'respondWithQuotedMessage': - if (!mid) return; - const message = await chat.data.getMessageByID(mid); - await chat.composer?.quoteMessage(message); - } - }, options); + } + + switch (processingType) { + case 'sendMessage': + if (!msg) return; + await chat.flows.sendMessage({ text: msg }); + return; + + case 'respondWithMessage': + if (!msg) return; + await chat.composer?.replyWith(msg); + return; + + case 'respondWithQuotedMessage': + if (!mid) return; + const message = await chat.data.getMessageByID(mid); + await chat.composer?.quoteMessage(message); + } + }, + + ...options, + }); }; diff --git a/apps/meteor/client/components/message/content/reactions/ReactionTooltip.tsx b/apps/meteor/client/components/message/content/reactions/ReactionTooltip.tsx index 13f13b838183..3d02999679e5 100644 --- a/apps/meteor/client/components/message/content/reactions/ReactionTooltip.tsx +++ b/apps/meteor/client/components/message/content/reactions/ReactionTooltip.tsx @@ -42,9 +42,10 @@ const ReactionTooltip = ({ emojiName, usernames, mine, messageId, showRealName, const getMessage = useGetMessageByID(); - const { data: users, isLoading } = useQuery( - ['chat.getMessage', 'reactions', messageId, usernames], - async () => { + const { data: users, isLoading } = useQuery({ + queryKey: ['chat.getMessage', 'reactions', messageId, usernames], + + queryFn: async () => { // This happens if the only reaction is from the current user if (!usernames.length) { return []; @@ -70,8 +71,9 @@ const ReactionTooltip = ({ emojiName, usernames, mine, messageId, showRealName, return reactions[emojiName].names || usernames; }, - { staleTime: 1000 * 60 * 5 }, - ); + + staleTime: 1000 * 60 * 5, + }); if (isLoading) { return ( diff --git a/apps/meteor/client/components/message/content/reactions/useToggleReactionMutation.ts b/apps/meteor/client/components/message/content/reactions/useToggleReactionMutation.ts index 9e9b3ca05599..52308f440630 100644 --- a/apps/meteor/client/components/message/content/reactions/useToggleReactionMutation.ts +++ b/apps/meteor/client/components/message/content/reactions/useToggleReactionMutation.ts @@ -14,11 +14,15 @@ export const useToggleReactionMutation = ( const uid = useUserId(); const reactToMessage = useEndpoint('POST', '/v1/chat.react'); - return useMutation(async ({ mid, reaction }) => { - if (!uid) { - throw new Error('Not logged in'); - } + return useMutation({ + mutationFn: async ({ mid, reaction }) => { + if (!uid) { + throw new Error('Not logged in'); + } - await reactToMessage({ messageId: mid, reaction }); - }, options); + await reactToMessage({ messageId: mid, reaction }); + }, + + ...options, + }); }; diff --git a/apps/meteor/client/components/message/hooks/usePinMessageMutation.ts b/apps/meteor/client/components/message/hooks/usePinMessageMutation.ts index 3405512dbe8b..6c59fb1f019f 100644 --- a/apps/meteor/client/components/message/hooks/usePinMessageMutation.ts +++ b/apps/meteor/client/components/message/hooks/usePinMessageMutation.ts @@ -26,7 +26,7 @@ export const usePinMessageMutation = () => { updatePinMessage(message, { pinned: false }); }, onSettled: (_data, _error, message) => { - queryClient.invalidateQueries(roomsQueryKeys.pinnedMessages(message.rid)); + queryClient.invalidateQueries({ queryKey: roomsQueryKeys.pinnedMessages(message.rid) }); }, }); }; diff --git a/apps/meteor/client/components/message/hooks/useStarMessageMutation.ts b/apps/meteor/client/components/message/hooks/useStarMessageMutation.ts index eabfc8692643..6454f60f1559 100644 --- a/apps/meteor/client/components/message/hooks/useStarMessageMutation.ts +++ b/apps/meteor/client/components/message/hooks/useStarMessageMutation.ts @@ -26,7 +26,7 @@ export const useStarMessageMutation = () => { dispatchToastMessage({ type: 'error', message: error }); }, onSettled: (_data, _error, message) => { - queryClient.invalidateQueries(roomsQueryKeys.starredMessages(message.rid)); + queryClient.invalidateQueries({ queryKey: roomsQueryKeys.starredMessages(message.rid) }); }, }); }; diff --git a/apps/meteor/client/components/message/hooks/useSubscriptionFromMessageQuery.ts b/apps/meteor/client/components/message/hooks/useSubscriptionFromMessageQuery.ts index 195032210e8d..8185f7cd7e44 100644 --- a/apps/meteor/client/components/message/hooks/useSubscriptionFromMessageQuery.ts +++ b/apps/meteor/client/components/message/hooks/useSubscriptionFromMessageQuery.ts @@ -6,7 +6,11 @@ import { useChat } from '../../../views/room/contexts/ChatContext'; export const useSubscriptionFromMessageQuery = (message: IMessage) => { const chat = useChat(); - return useQuery(['messages', message._id, 'subscription'], async () => { - return chat?.data.getSubscriptionFromMessage(message) ?? null; + return useQuery({ + queryKey: ['messages', message._id, 'subscription'], + + queryFn: async () => { + return chat?.data.getSubscriptionFromMessage(message) ?? null; + }, }); }; diff --git a/apps/meteor/client/components/message/hooks/useUnpinMessageMutation.ts b/apps/meteor/client/components/message/hooks/useUnpinMessageMutation.ts index f777929d5689..ed3880260dac 100644 --- a/apps/meteor/client/components/message/hooks/useUnpinMessageMutation.ts +++ b/apps/meteor/client/components/message/hooks/useUnpinMessageMutation.ts @@ -26,7 +26,7 @@ export const useUnpinMessageMutation = () => { updatePinMessage(message, { pinned: true }); }, onSettled: (_data, _error, message) => { - queryClient.invalidateQueries(roomsQueryKeys.pinnedMessages(message.rid)); + queryClient.invalidateQueries({ queryKey: roomsQueryKeys.pinnedMessages(message.rid) }); }, }); }; diff --git a/apps/meteor/client/components/message/hooks/useUnstarMessageMutation.ts b/apps/meteor/client/components/message/hooks/useUnstarMessageMutation.ts index 329e931fe116..353cd28d234c 100644 --- a/apps/meteor/client/components/message/hooks/useUnstarMessageMutation.ts +++ b/apps/meteor/client/components/message/hooks/useUnstarMessageMutation.ts @@ -26,7 +26,7 @@ export const useUnstarMessageMutation = () => { dispatchToastMessage({ type: 'error', message: error }); }, onSettled: (_data, _error, message) => { - queryClient.invalidateQueries(roomsQueryKeys.starredMessages(message.rid)); + queryClient.invalidateQueries({ queryKey: roomsQueryKeys.starredMessages(message.rid) }); }, }); }; diff --git a/apps/meteor/client/components/message/toolbar/useMessageActionAppsActionButtons.ts b/apps/meteor/client/components/message/toolbar/useMessageActionAppsActionButtons.ts index cecb79c183af..ba04cad4dfa5 100644 --- a/apps/meteor/client/components/message/toolbar/useMessageActionAppsActionButtons.ts +++ b/apps/meteor/client/components/message/toolbar/useMessageActionAppsActionButtons.ts @@ -1,7 +1,6 @@ import { type IUIActionButton, MessageActionContext as AppsEngineMessageActionContext } from '@rocket.chat/apps-engine/definition/ui'; import type { IMessage } from '@rocket.chat/core-typings'; import { useToastMessageDispatch } from '@rocket.chat/ui-contexts'; -import type { UseQueryResult } from '@tanstack/react-query'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -74,5 +73,5 @@ export const useMessageActionAppsActionButtons = (message: IMessage, context?: M return { ...result, data, - } as UseQueryResult; + }; }; diff --git a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVoipMenuOptions.tsx b/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVoipMenuOptions.tsx index b1497dbfe4a6..28b955765c49 100644 --- a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVoipMenuOptions.tsx +++ b/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVoipMenuOptions.tsx @@ -22,12 +22,12 @@ const useVoipMenuOptions = () => { const members = useMemo(() => uids.filter((uid) => uid !== ownUserId), [uids, ownUserId]); const remoteUserId = members[0]; - const { data: { user: remoteUser } = {}, isLoading } = useUserInfoQuery({ userId: remoteUserId }, { enabled: Boolean(remoteUserId) }); + const { data: { user: remoteUser } = {}, isPending } = useUserInfoQuery({ userId: remoteUserId }, { enabled: Boolean(remoteUserId) }); const isRemoteRegistered = !!remoteUser?.freeSwitchExtension; const isDM = members.length === 1; - const disabled = isMicPermissionDenied || !isDM || !isRemoteRegistered || !isRegistered || isInCall || isLoading; + const disabled = isMicPermissionDenied || !isDM || !isRemoteRegistered || !isRegistered || isInCall || isPending; const title = useMemo(() => { if (isMicPermissionDenied) { diff --git a/apps/meteor/client/hooks/useAppActionButtons.ts b/apps/meteor/client/hooks/useAppActionButtons.ts index b5796965b062..566baf69b37c 100644 --- a/apps/meteor/client/hooks/useAppActionButtons.ts +++ b/apps/meteor/client/hooks/useAppActionButtons.ts @@ -14,9 +14,12 @@ export const useAppActionButtons = const getActionButtons = useEndpoint('GET', '/apps/actionButtons'); - const result = useQuery(['apps', 'actionButtons'], () => getActionButtons(), { + const result = useQuery({ + queryKey: ['apps', 'actionButtons'], + queryFn: () => getActionButtons(), + ...(context && { - select: (data) => + select: (data: IUIActionButton[]) => data.filter( ( button, @@ -25,12 +28,15 @@ export const useAppActionButtons = } => button.context === context, ), }), + staleTime: Infinity, }); const invalidate = useDebouncedCallback( () => { - queryClient.invalidateQueries(['apps', 'actionButtons']); + queryClient.invalidateQueries({ + queryKey: ['apps', 'actionButtons'], + }); }, 100, [], diff --git a/apps/meteor/client/hooks/useAppSlashCommands.ts b/apps/meteor/client/hooks/useAppSlashCommands.ts index baa11ca00a69..3b3c45385cd6 100644 --- a/apps/meteor/client/hooks/useAppSlashCommands.ts +++ b/apps/meteor/client/hooks/useAppSlashCommands.ts @@ -14,7 +14,9 @@ export const useAppSlashCommands = () => { const invalidate = useDebouncedCallback( () => { - queryClient.invalidateQueries(['apps', 'slashCommands']); + queryClient.invalidateQueries({ + queryKey: ['apps', 'slashCommands'], + }); }, 100, [], @@ -36,9 +38,9 @@ export const useAppSlashCommands = () => { const getSlashCommands = useEndpoint('GET', '/v1/commands.list'); - useQuery( - ['apps', 'slashCommands'], - async () => { + const { data } = useQuery({ + queryKey: ['apps', 'slashCommands'] as const, + queryFn: async () => { let allCommands: Pick[] = []; let hasMore = true; let offset = 0; @@ -54,11 +56,14 @@ export const useAppSlashCommands = () => { return allCommands; }, - { - enabled: !!uid, - onSuccess(data) { - data.forEach((command) => slashCommands.add(command)); - }, - }, - ); + enabled: !!uid, + }); + + useEffect(() => { + if (!data) { + return; + } + + data.forEach((command) => slashCommands.add(command)); + }, [data]); }; diff --git a/apps/meteor/client/hooks/useEndpointAction.ts b/apps/meteor/client/hooks/useEndpointAction.ts index 4baf82a20ff2..96ed190f1588 100644 --- a/apps/meteor/client/hooks/useEndpointAction.ts +++ b/apps/meteor/client/hooks/useEndpointAction.ts @@ -21,7 +21,8 @@ export function useEndpointAction { if (options.successMessage) { dispatchToastMessage({ type: 'success', message: options.successMessage }); diff --git a/apps/meteor/client/hooks/useHighlightedCode.ts b/apps/meteor/client/hooks/useHighlightedCode.ts index e059bf3f1181..25036bb8b674 100644 --- a/apps/meteor/client/hooks/useHighlightedCode.ts +++ b/apps/meteor/client/hooks/useHighlightedCode.ts @@ -6,14 +6,18 @@ import hljs, { register } from '../../app/markdown/lib/hljs'; export function useHighlightedCode(language: string, text: string): string { const { t } = useTranslation(); - const { isLoading } = useQuery(['register-highlight-language', language], async () => { - try { - await register(language); - return true; - } catch (error) { - console.error('Not possible to register the provided language'); - } + const { isPending } = useQuery({ + queryKey: ['register-highlight-language', language], + + queryFn: async () => { + try { + await register(language); + return true; + } catch (error) { + console.error('Not possible to register the provided language'); + } + }, }); - return useMemo(() => (isLoading ? t('Loading') : hljs.highlight(language, text).value), [isLoading, language, text, t]); + return useMemo(() => (isPending ? t('Loading') : hljs.highlight(language, text).value), [isPending, language, text, t]); } diff --git a/apps/meteor/client/hooks/useLicense.ts b/apps/meteor/client/hooks/useLicense.ts index 6c50ff55fe74..c6f0c96a37dd 100644 --- a/apps/meteor/client/hooks/useLicense.ts +++ b/apps/meteor/client/hooks/useLicense.ts @@ -2,7 +2,7 @@ import type { Serialized } from '@rocket.chat/core-typings'; import type { OperationResult } from '@rocket.chat/rest-typings'; import { useEndpoint, useStream, useUserId } from '@rocket.chat/ui-contexts'; import type { QueryClient, UseQueryResult } from '@tanstack/react-query'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { keepPreviousData, useQuery, useQueryClient } from '@tanstack/react-query'; import { useEffect } from 'react'; type LicenseDataType = Serialized>>; @@ -18,7 +18,9 @@ const invalidateQueryClientLicenses = (() => { clearTimeout(timeout); timeout = setTimeout(() => { timeout = undefined; - queryClient.invalidateQueries(['licenses']); + queryClient.invalidateQueries({ + queryKey: ['licenses'], + }); }, milliseconds); }; })(); @@ -40,9 +42,11 @@ export const useLicenseBase = ({ useEffect(() => notify('license', () => invalidateQueries()), [notify, invalidateQueries]); - return useQuery(['licenses', 'getLicenses', params], () => getLicenses({ ...params }), { + return useQuery({ + queryKey: ['licenses', 'getLicenses', params], + queryFn: () => getLicenses({ ...params }), staleTime: Infinity, - keepPreviousData: true, + placeholderData: keepPreviousData, select, enabled: !!uid, }); diff --git a/apps/meteor/client/hooks/useLicenseLimitsByBehavior.ts b/apps/meteor/client/hooks/useLicenseLimitsByBehavior.ts index ba7e165496ea..46b86c732833 100644 --- a/apps/meteor/client/hooks/useLicenseLimitsByBehavior.ts +++ b/apps/meteor/client/hooks/useLicenseLimitsByBehavior.ts @@ -8,7 +8,7 @@ type LicenseLimitsByBehavior = Record; export const useLicenseLimitsByBehavior = () => { const result = useLicense({ loadValues: true }); - if (result.isLoading || result.isError) { + if (result.isPending || result.isError) { return null; } diff --git a/apps/meteor/client/hooks/useMessageboxAppsActionButtons.ts b/apps/meteor/client/hooks/useMessageboxAppsActionButtons.ts index 10c6f4f58ef4..2e2ab4b21ab9 100644 --- a/apps/meteor/client/hooks/useMessageboxAppsActionButtons.ts +++ b/apps/meteor/client/hooks/useMessageboxAppsActionButtons.ts @@ -1,5 +1,4 @@ import { useToastMessageDispatch } from '@rocket.chat/ui-contexts'; -import type { UseQueryResult } from '@tanstack/react-query'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -10,7 +9,7 @@ import type { MessageBoxAction } from '../../app/ui-utils/client/lib/messageBox' import { Utilities } from '../../ee/lib/misc/Utilities'; import { useUiKitActionManager } from '../uikit/hooks/useUiKitActionManager'; -export const useMessageboxAppsActionButtons = (): UseQueryResult => { +export const useMessageboxAppsActionButtons = () => { const result = useAppActionButtons('messageBoxAction'); const actionManager = useUiKitActionManager(); const dispatchToastMessage = useToastMessageDispatch(); @@ -52,11 +51,12 @@ export const useMessageboxAppsActionButtons = (): UseQueryResult; + }; }; diff --git a/apps/meteor/client/hooks/useReactiveQuery.ts b/apps/meteor/client/hooks/useReactiveQuery.ts index 61bffde48c26..9737e74f64e8 100644 --- a/apps/meteor/client/hooks/useReactiveQuery.ts +++ b/apps/meteor/client/hooks/useReactiveQuery.ts @@ -28,7 +28,7 @@ export const useReactiveQuery = { const getRegistrationStatus = useEndpoint('GET', '/v1/cloud.registrationStatus'); const canViewregistrationStatus = usePermission('manage-cloud'); - const queryResult = useQuery( - ['getRegistrationStatus'], - () => { + const queryResult = useQuery({ + queryKey: ['getRegistrationStatus'], + queryFn: () => { if (!canViewregistrationStatus) { throw new Error('unauthorized api call'); } return getRegistrationStatus(); }, - { - keepPreviousData: true, - staleTime: Infinity, - }, - ); + staleTime: Infinity, + }); - return { isRegistered: !queryResult.isLoading && queryResult.data?.registrationStatus?.workspaceRegistered, ...queryResult }; + return { isRegistered: !queryResult.isPending && queryResult.data?.registrationStatus?.workspaceRegistered, ...queryResult }; }; diff --git a/apps/meteor/client/hooks/useRoomInfoEndpoint.ts b/apps/meteor/client/hooks/useRoomInfoEndpoint.ts index 0bac1d7eb413..fbce560fd327 100644 --- a/apps/meteor/client/hooks/useRoomInfoEndpoint.ts +++ b/apps/meteor/client/hooks/useRoomInfoEndpoint.ts @@ -9,15 +9,19 @@ import type { Meteor } from 'meteor/meteor'; export const useRoomInfoEndpoint = (rid: IRoom['_id']): UseQueryResult> => { const getRoomInfo = useEndpoint('GET', '/v1/rooms.info'); const uid = useUserId(); - return useQuery(['/v1/rooms.info', rid], () => getRoomInfo({ roomId: rid }), { - cacheTime: minutesToMilliseconds(15), + return useQuery({ + queryKey: ['/v1/rooms.info', rid], + queryFn: () => getRoomInfo({ roomId: rid }), + gcTime: minutesToMilliseconds(15), staleTime: minutesToMilliseconds(5), + retry: (count, error: Meteor.Error) => { if (count > 2 || error.error === 'not-allowed') { return false; } return true; }, + enabled: !!uid, }); }; diff --git a/apps/meteor/client/hooks/useTranslationsForApps.ts b/apps/meteor/client/hooks/useTranslationsForApps.ts index 56e29c24a193..c1a4cd3fad54 100644 --- a/apps/meteor/client/hooks/useTranslationsForApps.ts +++ b/apps/meteor/client/hooks/useTranslationsForApps.ts @@ -41,7 +41,9 @@ export const useTranslationsForApps = () => { } const invalidate = withDebouncing({ wait: 100 })(() => { - queryClient.invalidateQueries(['apps', 'translations']); + queryClient.invalidateQueries({ + queryKey: ['apps', 'translations'], + }); }); const unsubscribe = subscribeToApps('apps', ([key]) => { diff --git a/apps/meteor/client/hooks/useUserDropdownAppsActionButtons.ts b/apps/meteor/client/hooks/useUserDropdownAppsActionButtons.ts index 69355590fe90..eb1f5a3823ff 100644 --- a/apps/meteor/client/hooks/useUserDropdownAppsActionButtons.ts +++ b/apps/meteor/client/hooks/useUserDropdownAppsActionButtons.ts @@ -21,7 +21,7 @@ export const useUserDropdownAppsActionButtons = () => { () => result.data ?.filter((action) => applyButtonFilters(action)) - .map((action) => { + .map((action): GenericMenuItemProps => { return { id: `${action.appId}_${action.actionId}`, // icon: action.icon as GenericMenuItemProps['icon'], @@ -52,5 +52,5 @@ export const useUserDropdownAppsActionButtons = () => { return { ...result, data, - } as UseQueryResult; + } as unknown as UseQueryResult; }; diff --git a/apps/meteor/client/hooks/useUserInfoQuery.ts b/apps/meteor/client/hooks/useUserInfoQuery.ts index fdbe793d60e3..371921087a5e 100644 --- a/apps/meteor/client/hooks/useUserInfoQuery.ts +++ b/apps/meteor/client/hooks/useUserInfoQuery.ts @@ -1,14 +1,18 @@ import type { UsersInfoParamsGet } from '@rocket.chat/rest-typings'; import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; type UserInfoQueryOptions = { enabled?: boolean; - keepPreviousData?: boolean; + placeholderData?: (previousData: T | undefined) => T | undefined; }; // a hook using tanstack useQuery and useEndpoint that fetches user information from the `users.info` endpoint -export const useUserInfoQuery = (params: UsersInfoParamsGet, options: UserInfoQueryOptions = { keepPreviousData: true }) => { +export const useUserInfoQuery = (params: UsersInfoParamsGet, options: UserInfoQueryOptions = { placeholderData: keepPreviousData }) => { const getUserInfo = useEndpoint('GET', '/v1/users.info'); - return useQuery(['users.info', params], () => getUserInfo({ ...params }), options); + return useQuery({ + queryKey: ['users.info', params], + queryFn: () => getUserInfo({ ...params }), + ...options, + }); }; diff --git a/apps/meteor/client/hooks/useWorkspaceInfo.ts b/apps/meteor/client/hooks/useWorkspaceInfo.ts index fbc9ba872556..e5efd1f6a508 100644 --- a/apps/meteor/client/hooks/useWorkspaceInfo.ts +++ b/apps/meteor/client/hooks/useWorkspaceInfo.ts @@ -1,7 +1,7 @@ import type { IStats, IWorkspaceInfo, Serialized } from '@rocket.chat/core-typings'; import type { IInstance } from '@rocket.chat/rest-typings'; import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useMutation, useQueries, useQueryClient } from '@tanstack/react-query'; +import { keepPreviousData, useMutation, useQueries, useQueryClient } from '@tanstack/react-query'; export const useWorkspaceInfo = ({ refreshStatistics }: { refreshStatistics?: boolean } = {}) => { const getStatistics = useEndpoint('GET', '/v1/statistics'); @@ -28,14 +28,15 @@ export const useWorkspaceInfo = ({ refreshStatistics }: { refreshStatistics?: bo return data as IWorkspaceInfo; }, staleTime: Infinity, - keepPreviousData: true, + placeholderData: keepPreviousData, }, { queryKey: ['info', 'instances'], queryFn: () => getInstances(), staleTime: Infinity, - keepPreviousData: true, - select({ instances }: Serialized<{ instances: IInstance[] }>) { + placeholderData: keepPreviousData, + select(data: unknown) { + const { instances } = data as Serialized<{ instances: IInstance[] }>; return instances.map((instance) => ({ ...instance, ...(instance.instanceRecord && { @@ -51,11 +52,14 @@ export const useWorkspaceInfo = ({ refreshStatistics }: { refreshStatistics?: bo queryKey: ['info', 'statistics'], queryFn: () => getStatistics({ refresh: refreshStatistics ? 'true' : 'false' }), staleTime: Infinity, - keepPreviousData: true, - select: (data: Serialized) => ({ - ...data, - lastMessageSentAt: data.lastMessageSentAt ? new Date(data.lastMessageSentAt) : undefined, - }), + placeholderData: keepPreviousData, + select: (data: unknown) => { + const statsData = data as Serialized; + return { + ...statsData, + lastMessageSentAt: statsData.lastMessageSentAt ? new Date(statsData.lastMessageSentAt) : undefined, + }; + }, }, ], }); @@ -64,6 +68,9 @@ export const useWorkspaceInfo = ({ refreshStatistics }: { refreshStatistics?: bo export const useRefreshStatistics = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: () => queryClient.invalidateQueries(['info', 'statistics']), + mutationFn: () => + queryClient.invalidateQueries({ + queryKey: ['info', 'statistics'], + }), }); }; diff --git a/apps/meteor/client/hooks/webdav/useWebDAVAccountIntegrationsQuery.ts b/apps/meteor/client/hooks/webdav/useWebDAVAccountIntegrationsQuery.ts index 171490b33d18..3381e03abf5f 100644 --- a/apps/meteor/client/hooks/webdav/useWebDAVAccountIntegrationsQuery.ts +++ b/apps/meteor/client/hooks/webdav/useWebDAVAccountIntegrationsQuery.ts @@ -39,7 +39,7 @@ export const useWebDAVAccountIntegrationsQuery = ({ enabled = true, ...options } return subscribeToNotifyUser(`${uid}/webdav`, ({ type, account }) => { switch (type) { case 'changed': - queryClient.invalidateQueries(queryKey); + queryClient.invalidateQueries({ queryKey }); break; case 'removed': diff --git a/apps/meteor/client/lib/queryClient.ts b/apps/meteor/client/lib/queryClient.ts index 2bb38d001242..f24351738f9c 100644 --- a/apps/meteor/client/lib/queryClient.ts +++ b/apps/meteor/client/lib/queryClient.ts @@ -3,7 +3,6 @@ import { QueryClient } from '@tanstack/react-query'; export const queryClient = new QueryClient({ defaultOptions: { queries: { - onError: console.warn, refetchOnWindowFocus: false, retry: process.env.TEST_MODE === 'true', }, diff --git a/apps/meteor/client/omnichannel/additionalForms/DepartmentBusinessHours.tsx b/apps/meteor/client/omnichannel/additionalForms/DepartmentBusinessHours.tsx index aa8a34889245..1d40dc116c74 100644 --- a/apps/meteor/client/omnichannel/additionalForms/DepartmentBusinessHours.tsx +++ b/apps/meteor/client/omnichannel/additionalForms/DepartmentBusinessHours.tsx @@ -9,7 +9,10 @@ export const DepartmentBusinessHours = ({ bhId }: { bhId: string | undefined }) const { t } = useTranslation(); const hasLicense = useHasLicenseModule('livechat-enterprise'); const getBusinessHour = useEndpoint('GET', '/v1/livechat/business-hour'); - const { data } = useQuery(['/v1/livechat/business-hour', bhId], () => getBusinessHour({ _id: bhId, type: 'custom' })); + const { data } = useQuery({ + queryKey: ['/v1/livechat/business-hour', bhId], + queryFn: () => getBusinessHour({ _id: bhId, type: 'custom' }), + }); const name = data?.businessHour?.name; diff --git a/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx b/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx index 62937dbc4005..01c5d64abad6 100644 --- a/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx +++ b/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx @@ -35,9 +35,11 @@ const BusinessHoursTable = () => { ); const getBusinessHours = useEndpoint('GET', '/v1/livechat/business-hours'); - const { data, isLoading, isSuccess, isError, refetch } = useQuery(['livechat-getBusinessHours', query], async () => - getBusinessHours(query), - ); + const { data, isLoading, isSuccess, isError, refetch } = useQuery({ + queryKey: ['livechat-getBusinessHours', query], + + queryFn: async () => getBusinessHours(query), + }); const headers = ( <> diff --git a/apps/meteor/client/omnichannel/businessHours/useRemoveBusinessHour.tsx b/apps/meteor/client/omnichannel/businessHours/useRemoveBusinessHour.tsx index 27ae0c6c4e29..ad39b51a2451 100644 --- a/apps/meteor/client/omnichannel/businessHours/useRemoveBusinessHour.tsx +++ b/apps/meteor/client/omnichannel/businessHours/useRemoveBusinessHour.tsx @@ -17,7 +17,9 @@ export const useRemoveBusinessHour = () => { try { await removeBusinessHour(_id, type); dispatchToastMessage({ type: 'success', message: t('Business_Hour_Removed') }); - queryClient.invalidateQueries(['livechat-getBusinessHours']); + queryClient.invalidateQueries({ + queryKey: ['livechat-getBusinessHours'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } finally { diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx index 7fc1ee18f9e0..b5f63dcaaaf2 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx @@ -55,7 +55,9 @@ const CannedResponseEdit = ({ cannedResponseData }: CannedResponseEditProps) => message: t(cannedResponseData?._id ? 'Canned_Response_Updated' : 'Canned_Response_Created'), }); router.navigate('/omnichannel/canned-responses'); - queryClient.invalidateQueries(['getCannedResponses']); + queryClient.invalidateQueries({ + queryKey: ['getCannedResponses'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx index cf4ab9523cb4..e6e457241e82 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx @@ -12,9 +12,12 @@ const CannedResponseEditWithData = ({ cannedResponseId }: { cannedResponseId: IO const { t } = useTranslation(); const getCannedResponseById = useEndpoint('GET', '/v1/canned-responses/:_id', { _id: cannedResponseId }); - const { data, isLoading, isError } = useQuery(['getCannedResponseById', cannedResponseId], async () => getCannedResponseById()); + const { data, isPending, isError } = useQuery({ + queryKey: ['getCannedResponseById', cannedResponseId], + queryFn: async () => getCannedResponseById(), + }); - if (isLoading) { + if (isPending) { return ; } @@ -30,7 +33,7 @@ const CannedResponseEditWithData = ({ cannedResponseId }: { cannedResponseId: IO return ; } - return ; + return ; }; export default CannedResponseEditWithData; diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx index 50b720664c1b..697c0e16b75f 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx @@ -2,7 +2,7 @@ import { Box, IconButton, Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { UserAvatar } from '@rocket.chat/ui-avatar'; import { useTranslation, usePermission, useToastMessageDispatch, useEndpoint, useRouter } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { hashKey, useQuery } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import CannedResponseFilter from './CannedResponseFilter'; @@ -52,11 +52,13 @@ const CannedResponsesTable = () => { [createdBy, current, debouncedText, itemsPerPage, sharing, sortBy, sortDirection], ); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const getCannedResponses = useEndpoint('GET', '/v1/canned-responses'); - const { data, isLoading, isSuccess } = useQuery(['getCannedResponses', query], () => getCannedResponses(query), { + const { data, isLoading, isSuccess } = useQuery({ + queryKey: ['getCannedResponses', query], + queryFn: () => getCannedResponses(query), refetchOnWindowFocus: false, }); diff --git a/apps/meteor/client/omnichannel/cannedResponses/useRemoveCannedResponse.tsx b/apps/meteor/client/omnichannel/cannedResponses/useRemoveCannedResponse.tsx index 850767336283..c70908b0ad26 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/useRemoveCannedResponse.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/useRemoveCannedResponse.tsx @@ -18,7 +18,9 @@ export const useRemoveCannedResponse = () => { const onDeleteCannedResponse: () => Promise = async () => { try { await removeCannedResponse(id); - queryClient.invalidateQueries(['getCannedResponses']); + queryClient.invalidateQueries({ + queryKey: ['getCannedResponses'], + }); router.navigate('/omnichannel/canned-responses'); dispatchToastMessage({ type: 'success', message: t('Canned_Response_Removed') }); } catch (error) { diff --git a/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx b/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx index 1f6b01f2f110..b23d2b4a46d3 100644 --- a/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx +++ b/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx @@ -21,8 +21,12 @@ export const useOmnichannelPrioritiesMenu = (rid: string): ComponentProps async () => { try { priorityId ? await updateRoomPriority({ priorityId }) : await removeRoomPriority(); - queryClient.invalidateQueries(['current-chats']); - queryClient.invalidateQueries(['/v1/rooms.info', rid]); + queryClient.invalidateQueries({ + queryKey: ['current-chats'], + }); + queryClient.invalidateQueries({ + queryKey: ['/v1/rooms.info', rid], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } diff --git a/apps/meteor/client/omnichannel/monitors/MonitorsTable.tsx b/apps/meteor/client/omnichannel/monitors/MonitorsTable.tsx index ac36e7a81301..be14aaff923e 100644 --- a/apps/meteor/client/omnichannel/monitors/MonitorsTable.tsx +++ b/apps/meteor/client/omnichannel/monitors/MonitorsTable.tsx @@ -15,7 +15,7 @@ import { import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { UserAutoComplete } from '@rocket.chat/ui-client'; import { useTranslation, useToastMessageDispatch, useMethod, useEndpoint, useSetModal } from '@rocket.chat/ui-contexts'; -import { useMutation, useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useMutation, useQuery, hashKey, useQueryClient } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import FilterByText from '../../components/FilterByText'; @@ -32,7 +32,6 @@ import { } from '../../components/GenericTable'; import { usePagination } from '../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../components/GenericTable/hooks/useSort'; -import { queryClient } from '../../lib/queryClient'; const MonitorsTable = () => { const t = useTranslation(); @@ -68,16 +67,21 @@ const MonitorsTable = () => { 500, ); - const { data, refetch, isLoading, isSuccess, isError } = useQuery(['omnichannel', 'monitors', query], () => getMonitors(query)); + const { data, refetch, isLoading, isSuccess, isError } = useQuery({ + queryKey: ['omnichannel', 'monitors', query], + queryFn: () => getMonitors(query), + }); + + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const queryClient = useQueryClient(); const addMutation = useMutation({ mutationFn: async (username: string) => { await addMonitor(username); - await queryClient.invalidateQueries(['omnichannel', 'monitors']); + await queryClient.invalidateQueries({ queryKey: ['omnichannel', 'monitors'] }); }, onSuccess: () => { setUsername(''); @@ -100,7 +104,7 @@ const MonitorsTable = () => { } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } - queryClient.invalidateQueries(['omnichannel', 'monitors']); + queryClient.invalidateQueries({ queryKey: ['omnichannel', 'monitors'] }); setModal(); }; @@ -138,7 +142,7 @@ const MonitorsTable = () => { {t('Username')} void} /> - diff --git a/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx b/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx index 9c98100259f6..3f0e6e13d8c2 100644 --- a/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx +++ b/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx @@ -42,7 +42,10 @@ export const PrioritiesPage = ({ priorityId, context }: PrioritiesPageProps): Re setModal(null); await resetPriorities(); - await queryClient.invalidateQueries(['/v1/livechat/priorities'], { exact: true }); + await queryClient.invalidateQueries({ + queryKey: ['/v1/livechat/priorities'], + exact: true, + }); prioritiesRoute.push({}); dispatchToastMessage({ type: 'success', message: t('Priorities_restored') }); @@ -66,10 +69,15 @@ export const PrioritiesPage = ({ priorityId, context }: PrioritiesPageProps): Re const onSavePriority = async ({ reset, ...payload }: PriorityFormData): Promise => { await savePriority(reset ? { reset } : payload); - await queryClient.invalidateQueries(['/v1/livechat/priorities']); + await queryClient.invalidateQueries({ + queryKey: ['/v1/livechat/priorities'], + }); dispatchToastMessage({ type: 'success', message: t('Priority_saved') }); - await queryClient.invalidateQueries(['/v1/livechat/priorities'], { exact: true }); + await queryClient.invalidateQueries({ + queryKey: ['/v1/livechat/priorities'], + exact: true, + }); prioritiesRoute.push({}); }; diff --git a/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx b/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx index 6a26a5a83449..8ab891423182 100644 --- a/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx +++ b/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx @@ -13,9 +13,9 @@ type PriorityEditFormWithDataProps = Omit & { function PriorityEditFormWithData({ priorityId, ...props }: PriorityEditFormWithDataProps): ReactElement { const { t } = useTranslation(); - const { data, isInitialLoading, isError } = usePriorityInfo(priorityId); + const { data, isLoading, isError } = usePriorityInfo(priorityId); - if (isInitialLoading) { + if (isLoading) { return ; } diff --git a/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx b/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx index ee8abb02b7fb..f6d2f2eaaf26 100644 --- a/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx +++ b/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx @@ -12,7 +12,7 @@ type ReportCardProps = { children: ReactElement; periodSelectorProps: ComponentProps; downloadProps: ComponentProps; - isLoading?: boolean; + isPending?: boolean; isDataFound?: boolean; minHeight?: number; subtitle?: string; @@ -23,12 +23,12 @@ type ReportCardProps = { }; export const ReportCard = forwardRef(function ReportCard( - { id, title, children, periodSelectorProps, downloadProps, isLoading, isDataFound, subtitle, emptyStateSubtitle, isError, onRetry }, + { id, title, children, periodSelectorProps, downloadProps, isPending, isDataFound, subtitle, emptyStateSubtitle, isError, onRetry }, ref, ) { return ( - + {title} @@ -46,7 +46,7 @@ export const ReportCard = forwardRef(function Repo void; children: ReactElement; }; -export const ReportCardContent = ({ isLoading, isError, isDataFound, subtitle, onRetry, children }: ReportCardContentProps) => { - if (isLoading) { +export const ReportCardContent = ({ isPending, isError, isDataFound, subtitle, onRetry, children }: ReportCardContentProps) => { + if (isPending) { return ; } if (isError) { diff --git a/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx index bf0f5f8e80bf..934d7ca6ebf9 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx @@ -25,12 +25,13 @@ export const useAgentsSection = () => { const { data: { data, total = 0, unspecified = 0 } = { data: [], total: 0 }, refetch, - isLoading, + isPending, isError, isSuccess, - } = useQuery( - ['omnichannel-reports', 'conversations-by-agent', period, sortBy, sortDirection], - async () => { + } = useQuery({ + queryKey: ['omnichannel-reports', 'conversations-by-agent', period, sortBy, sortDirection], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getConversationsByAgent({ start: start.toISOString(), @@ -39,10 +40,9 @@ export const useAgentsSection = () => { }); return { ...response, data: formatChartData(response.data) }; }, - { - refetchInterval: 5 * 60 * 1000, - }, - ); + + refetchInterval: 5 * 60 * 1000, + }); const title = t('Conversations_by_agents'); @@ -65,7 +65,7 @@ export const useAgentsSection = () => { emptyStateSubtitle, data, total, - isLoading, + isPending, isError, isDataFound: isSuccess && data.length > 0, periodSelectorProps, @@ -82,7 +82,7 @@ export const useAgentsSection = () => { emptyStateSubtitle, data, total, - isLoading, + isPending, isError, isSuccess, periodSelectorProps, diff --git a/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx index 9a90fb982814..b7d4f47cc851 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx @@ -46,22 +46,22 @@ export const useChannelsSection = () => { const { data: { data, rawData, total } = { data: [], rawData: [], total: 0 }, refetch, - isLoading, + isPending, isError, isSuccess, - } = useQuery( - ['omnichannel-reports', 'conversations-by-source', period], - async () => { + } = useQuery({ + queryKey: ['omnichannel-reports', 'conversations-by-source', period], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getConversationsBySource({ start: start.toISOString(), end: end.toISOString() }); const data = formatChartData(response.data, response.total, t); const displayData: DataItem[] = getTop(5, data, (value) => formatItem({ label: t('Others'), value }, response.total, t)); return { ...response, data: displayData, rawData: data }; }, - { - refetchInterval: 5 * 60 * 1000, - }, - ); + + refetchInterval: 5 * 60 * 1000, + }); const title = t('Conversations_by_channel'); const subtitle = t('__count__conversations__period__', { @@ -80,7 +80,7 @@ export const useChannelsSection = () => { emptyStateSubtitle, data, total, - isLoading, + isPending, isError, isDataFound: isSuccess && data.length > 0, periodSelectorProps, @@ -88,6 +88,6 @@ export const useChannelsSection = () => { downloadProps, onRetry: refetch, }), - [title, subtitle, emptyStateSubtitle, data, total, isLoading, isError, isSuccess, periodSelectorProps, period, downloadProps, refetch], + [title, subtitle, emptyStateSubtitle, data, total, isPending, isError, isSuccess, periodSelectorProps, period, downloadProps, refetch], ); }; diff --git a/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx index 57f30d0d38de..7ea2800c2c5e 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx @@ -22,21 +22,21 @@ export const useDepartmentsSection = () => { const { data: { data, total = 0, unspecified = 0 } = { data: [], total: 0 }, - isLoading, + isPending, isError, isSuccess, refetch, - } = useQuery( - ['omnichannel-reports', 'conversations-by-department', period], - async () => { + } = useQuery({ + queryKey: ['omnichannel-reports', 'conversations-by-department', period], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getConversationsByDepartment({ start: start.toISOString(), end: end.toISOString() }); return { ...response, data: formatChartData(response.data) }; }, - { - refetchInterval: 5 * 60 * 1000, - }, - ); + + refetchInterval: 5 * 60 * 1000, + }); const title = t('Conversations_by_department'); const subtitleTotals = t('__departments__departments_and__count__conversations__period__', { @@ -58,7 +58,7 @@ export const useDepartmentsSection = () => { emptyStateSubtitle, data, total, - isLoading, + isPending, isError, isDataFound: isSuccess && data.length > 0, periodSelectorProps, @@ -66,6 +66,6 @@ export const useDepartmentsSection = () => { downloadProps, onRetry: refetch, }), - [title, subtitle, emptyStateSubtitle, data, total, isLoading, isError, isSuccess, periodSelectorProps, period, downloadProps, refetch], + [title, subtitle, emptyStateSubtitle, data, total, isPending, isError, isSuccess, periodSelectorProps, period, downloadProps, refetch], ); }; diff --git a/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx index d001a8bbeb5f..1ece5f941523 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx @@ -42,21 +42,21 @@ export const useStatusSection = () => { const { data: { data, total } = { data: [], total: 0 }, - isLoading, + isPending, isError, isSuccess, refetch, - } = useQuery( - ['omnichannel-reports', 'conversations-by-status', period, t], - async () => { + } = useQuery({ + queryKey: ['omnichannel-reports', 'conversations-by-status', period, t], + + queryFn: async () => { const response = await getConversationsByStatus({ start: start.toISOString(), end: end.toISOString() }); return { ...response, data: formatChartData(response.data, response.total, t) }; }, - { - refetchInterval: 5 * 60 * 1000, - }, - ); + + refetchInterval: 5 * 60 * 1000, + }); const title = t('Conversations_by_status'); const subtitle = t('__count__conversations__period__', { @@ -78,11 +78,11 @@ export const useStatusSection = () => { period, periodSelectorProps, downloadProps, - isLoading, + isPending, isError, isDataFound: isSuccess && data.length > 0, onRetry: refetch, }), - [title, subtitle, emptyStateSubtitle, data, total, period, periodSelectorProps, downloadProps, isLoading, isError, isSuccess, refetch], + [title, subtitle, emptyStateSubtitle, data, total, period, periodSelectorProps, downloadProps, isPending, isError, isSuccess, refetch], ); }; diff --git a/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx index 5ba58a71c879..37e9793c1c19 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx @@ -31,20 +31,20 @@ export const useTagsSection = () => { const { data: { data, total = 0, unspecified = 0 } = { data: [], total: 0 }, refetch, - isLoading, + isPending, isError, isSuccess, - } = useQuery( - ['omnichannel-reports', 'conversations-by-tags', period], - async () => { + } = useQuery({ + queryKey: ['omnichannel-reports', 'conversations-by-tags', period], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getConversationsByTags({ start: start.toISOString(), end: end.toISOString() }); return { ...response, data: formatChartData(response.data) }; }, - { - refetchInterval: 5 * 60 * 1000, - }, - ); + + refetchInterval: 5 * 60 * 1000, + }); const title = t('Conversations_by_tag'); const subtitleTotals = t('__count__tags__and__count__conversations__period__', { @@ -70,10 +70,10 @@ export const useTagsSection = () => { periodSelectorProps, downloadProps, isError, - isLoading, + isPending, isDataFound: isSuccess && data.length > 0, onRetry: refetch, }), - [title, subtitle, emptyStateSubtitle, data, total, isError, isLoading, isSuccess, periodSelectorProps, period, downloadProps, refetch], + [title, subtitle, emptyStateSubtitle, data, total, isError, isPending, isSuccess, periodSelectorProps, period, downloadProps, refetch], ); }; diff --git a/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx b/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx index 67560bc6e8a9..0f722340e26a 100644 --- a/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx +++ b/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx @@ -14,10 +14,13 @@ type SlaEditProps = { function SlaEditWithData({ slaId, reload }: SlaEditProps): ReactElement { const getSLA = useEndpoint('GET', `/v1/livechat/sla/:slaId`, { slaId }); - const { data, isLoading, isError } = useQuery(['/v1/livechat/sla', slaId], () => getSLA()); + const { data, isPending, isError } = useQuery({ + queryKey: ['/v1/livechat/sla', slaId], + queryFn: () => getSLA(), + }); const { t } = useTranslation(); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx b/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx index 098e0f948f37..225033613ad4 100644 --- a/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx +++ b/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx @@ -1,7 +1,7 @@ import { Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useEndpoint, useRouter } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useQuery, hashKey } from '@tanstack/react-query'; import type { MutableRefObject } from 'react'; import { useMemo, useState, useEffect } from 'react'; @@ -43,10 +43,13 @@ const SlaTable = ({ reload }: { reload: MutableRefObject<() => void> }) => { ); const getSlaData = useEndpoint('GET', '/v1/livechat/sla'); - const { data, isSuccess, isLoading, refetch } = useQuery(['/v1/livechat/sla', query], () => getSlaData(query)); + const { data, isSuccess, isLoading, refetch } = useQuery({ + queryKey: ['/v1/livechat/sla', query], + queryFn: () => getSlaData(query), + }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); useEffect(() => { reload.current = refetch; diff --git a/apps/meteor/client/omnichannel/tags/TagEdit.tsx b/apps/meteor/client/omnichannel/tags/TagEdit.tsx index 0e700f6903df..af174af4e042 100644 --- a/apps/meteor/client/omnichannel/tags/TagEdit.tsx +++ b/apps/meteor/client/omnichannel/tags/TagEdit.tsx @@ -58,7 +58,9 @@ const TagEdit = ({ tagData, currentDepartments }: TagEditProps) => { try { await saveTag(_id as unknown as string, { name, description }, departmentsId); dispatchToastMessage({ type: 'success', message: t('Saved') }); - queryClient.invalidateQueries(['livechat-tags']); + queryClient.invalidateQueries({ + queryKey: ['livechat-tags'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } finally { diff --git a/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx b/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx index 3b4dd345bd0c..15785952bd56 100644 --- a/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx +++ b/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx @@ -12,9 +12,13 @@ const TagEditWithData = ({ tagId }: { tagId: ILivechatTag['_id'] }) => { const { t } = useTranslation(); const getTagById = useEndpoint('GET', '/v1/livechat/tags/:tagId', { tagId }); - const { data, isLoading, isError } = useQuery(['livechat-getTagById', tagId], async () => getTagById(), { refetchOnWindowFocus: false }); + const { data, isPending, isError } = useQuery({ + queryKey: ['livechat-getTagById', tagId], + queryFn: async () => getTagById(), + refetchOnWindowFocus: false, + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx b/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx index bac6b7d03741..1ec8de7a83ba 100644 --- a/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx +++ b/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx @@ -10,13 +10,13 @@ const TagEditWithDepartmentData = ({ tagData }: { tagData: ILivechatTag }) => { const t = useTranslation(); const getDepartmentsById = useEndpoint('GET', '/v1/livechat/department.listByIds'); - const { data, isLoading, isError } = useQuery( - ['livechat-getDepartmentsById', tagData.departments], - async () => getDepartmentsById({ ids: tagData.departments }), - { refetchOnWindowFocus: false }, - ); + const { data, isPending, isError } = useQuery({ + queryKey: ['livechat-getDepartmentsById', tagData.departments], + queryFn: async () => getDepartmentsById({ ids: tagData.departments }), + refetchOnWindowFocus: false, + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/omnichannel/tags/TagsTable.tsx b/apps/meteor/client/omnichannel/tags/TagsTable.tsx index 28f020aebb96..a3047d062ac6 100644 --- a/apps/meteor/client/omnichannel/tags/TagsTable.tsx +++ b/apps/meteor/client/omnichannel/tags/TagsTable.tsx @@ -1,7 +1,7 @@ import { IconButton, Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useEndpoint, useRouter } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useQuery, hashKey } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import { useRemoveTag } from './useRemoveTag'; @@ -46,10 +46,14 @@ const TagsTable = () => { ); const getTags = useEndpoint('GET', '/v1/livechat/tags'); - const { data, isSuccess, isLoading } = useQuery(['livechat-tags', query], async () => getTags(query), { refetchOnWindowFocus: false }); + const { data, isSuccess, isLoading } = useQuery({ + queryKey: ['livechat-tags', query], + queryFn: async () => getTags(query), + refetchOnWindowFocus: false, + }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/omnichannel/tags/useRemoveTag.tsx b/apps/meteor/client/omnichannel/tags/useRemoveTag.tsx index aaa5c980f09b..ac6f6e3a305d 100644 --- a/apps/meteor/client/omnichannel/tags/useRemoveTag.tsx +++ b/apps/meteor/client/omnichannel/tags/useRemoveTag.tsx @@ -19,7 +19,9 @@ export const useRemoveTag = () => { await removeTag(tagId); dispatchToastMessage({ type: 'success', message: t('Tag_removed') }); router.navigate('/omnichannel/tags'); - queryClient.invalidateQueries(['livechat-tags']); + queryClient.invalidateQueries({ + queryKey: ['livechat-tags'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } finally { diff --git a/apps/meteor/client/omnichannel/units/UnitEdit.tsx b/apps/meteor/client/omnichannel/units/UnitEdit.tsx index 1d00819edafc..e1be47d35e5f 100644 --- a/apps/meteor/client/omnichannel/units/UnitEdit.tsx +++ b/apps/meteor/client/omnichannel/units/UnitEdit.tsx @@ -138,7 +138,9 @@ const UnitEdit = ({ unitData, unitMonitors, unitDepartments }: UnitEditProps) => try { await saveUnit(_id as unknown as string, { name, visibility }, monitorsData, departmentsData); dispatchToastMessage({ type: 'success', message: t('Saved') }); - queryClient.invalidateQueries(['livechat-units']); + queryClient.invalidateQueries({ + queryKey: ['livechat-units'], + }); router.navigate('/omnichannel/units'); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); diff --git a/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx b/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx index fed6c8eaf14b..46e1bf608c76 100644 --- a/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx +++ b/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx @@ -18,17 +18,27 @@ const UnitEditWithData = ({ unitId }: { unitId: IOmnichannelBusinessUnit['_id'] data: unitData, isError, isLoading, - } = useQuery(['livechat-getUnitById', unitId], async () => getUnitById(), { refetchOnWindowFocus: false }); + } = useQuery({ + queryKey: ['livechat-getUnitById', unitId], + queryFn: async () => getUnitById(), + refetchOnWindowFocus: false, + }); const { data: unitMonitors, isError: unitMonitorsError, isLoading: unitMonitorsLoading, - } = useQuery(['livechat-getMonitorsByUnitId', unitId], async () => getMonitorsByUnitId({ unitId }), { refetchOnWindowFocus: false }); + } = useQuery({ + queryKey: ['livechat-getMonitorsByUnitId', unitId], + queryFn: async () => getMonitorsByUnitId({ unitId }), + refetchOnWindowFocus: false, + }); const { data: unitDepartments, isError: unitDepartmentsError, isLoading: unitDepartmentsLoading, - } = useQuery(['livechat-getDepartmentsByUnitId', unitId], async () => getDepartmentsByUnitId({ unitId }), { + } = useQuery({ + queryKey: ['livechat-getDepartmentsByUnitId', unitId], + queryFn: async () => getDepartmentsByUnitId({ unitId }), refetchOnWindowFocus: false, }); @@ -44,7 +54,7 @@ const UnitEditWithData = ({ unitId }: { unitId: IOmnichannelBusinessUnit['_id'] ); } - return ; + return ; }; export default UnitEditWithData; diff --git a/apps/meteor/client/omnichannel/units/UnitsTable.tsx b/apps/meteor/client/omnichannel/units/UnitsTable.tsx index 85bdda9d28a6..18b00bf06bd3 100644 --- a/apps/meteor/client/omnichannel/units/UnitsTable.tsx +++ b/apps/meteor/client/omnichannel/units/UnitsTable.tsx @@ -1,7 +1,7 @@ import { Pagination, IconButton } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useEndpoint, useRouter } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useQuery, hashKey } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -42,10 +42,13 @@ const UnitsTable = () => { ); const getUnits = useEndpoint('GET', '/v1/livechat/units'); - const { isSuccess, isLoading, data } = useQuery(['livechat-units', query], async () => getUnits(query)); + const { isSuccess, isLoading, data } = useQuery({ + queryKey: ['livechat-units', query], + queryFn: async () => getUnits(query), + }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const handleAddNew = useMutableCallback(() => router.navigate('/omnichannel/units/new')); const onRowClick = useMutableCallback((id) => () => router.navigate(`/omnichannel/units/edit/${id}`)); diff --git a/apps/meteor/client/omnichannel/units/useRemoveUnit.tsx b/apps/meteor/client/omnichannel/units/useRemoveUnit.tsx index faf09b76442c..c6faa7f8a9ae 100644 --- a/apps/meteor/client/omnichannel/units/useRemoveUnit.tsx +++ b/apps/meteor/client/omnichannel/units/useRemoveUnit.tsx @@ -19,7 +19,9 @@ export const useRemoveUnit = () => { await removeUnit(id); dispatchToastMessage({ type: 'success', message: t('Unit_removed') }); router.navigate('/omnichannel/units'); - queryClient.invalidateQueries(['livechat-units']); + queryClient.invalidateQueries({ + queryKey: ['livechat-units'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } finally { diff --git a/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx b/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx index 4fda5157424b..7030b04407e3 100644 --- a/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx +++ b/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx @@ -1,6 +1,6 @@ import { useDebouncedCallback } from '@rocket.chat/fuselage-hooks'; import { usePermission, useStream } from '@rocket.chat/ui-contexts'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { keepPreviousData, useQuery, useQueryClient } from '@tanstack/react-query'; import type { ReactNode } from 'react'; import { useEffect } from 'react'; @@ -44,7 +44,7 @@ const AppsProvider = ({ children }: AppsProviderProps) => { const queryClient = useQueryClient(); - const { isLoading: isLicenseInformationLoading, data: { license, limits } = {} } = useLicense({ loadValues: true }); + const { isPending: isLicenseInformationLoading, data: { license, limits } = {} } = useLicense({ loadValues: true }); const isEnterprise = isLicenseInformationLoading ? undefined : !!license; const invalidateAppsCountQuery = useInvalidateAppsCountQueryCallback(); @@ -54,7 +54,9 @@ const AppsProvider = ({ children }: AppsProviderProps) => { const invalidate = useDebouncedCallback( () => { - queryClient.invalidateQueries(['marketplace', 'apps-instance']); + queryClient.invalidateQueries({ + queryKey: ['marketplace', 'apps-instance'], + }); invalidateAppsCountQuery(); }, 100, @@ -72,26 +74,25 @@ const AppsProvider = ({ children }: AppsProviderProps) => { }); }, [invalidate, invalidateLicenseQuery, isEnterprise, stream]); - const marketplace = useQuery( - ['marketplace', 'apps-marketplace', isAdminUser], - async () => { + const marketplace = useQuery({ + queryKey: ['marketplace', 'apps-marketplace', isAdminUser], + + queryFn: async () => { const result = await AppClientOrchestratorInstance.getAppsFromMarketplace(isAdminUser); - queryClient.invalidateQueries(['marketplace', 'apps-stored']); if (result.error && typeof result.error === 'string') { throw new Error(result.error); } return result.apps; }, - { - staleTime: Infinity, - keepPreviousData: true, - onSettled: () => queryClient.invalidateQueries(['marketplace', 'apps-stored']), - }, - ); - const instance = useQuery( - ['marketplace', 'apps-instance', isAdminUser], - async () => { + staleTime: Infinity, + placeholderData: keepPreviousData, + }); + + const instance = useQuery({ + queryKey: ['marketplace', 'apps-instance', isAdminUser], + + queryFn: async () => { const result = await AppClientOrchestratorInstance.getInstalledApps().then((result: App[]) => result.map((current: App) => ({ ...current, @@ -100,24 +101,28 @@ const AppsProvider = ({ children }: AppsProviderProps) => { ); return result; }, - { - staleTime: Infinity, - refetchOnMount: 'always', - onSettled: () => queryClient.invalidateQueries(['marketplace', 'apps-stored']), - }, - ); - const { isLoading: isMarketplaceDataLoading, data: marketplaceData } = useQuery( - ['marketplace', 'apps-stored', instance.data, marketplace.data], - () => storeQueryFunction(marketplace, instance), - { - enabled: marketplace.isFetched && instance.isFetched, - keepPreviousData: true, - }, - ); + staleTime: Infinity, + refetchOnMount: 'always', + }); + + const { isPending: isMarketplaceDataLoading, data: marketplaceData } = useQuery({ + queryKey: ['marketplace', 'apps-stored', instance.data, marketplace.data], + queryFn: () => storeQueryFunction(marketplace, instance), + enabled: marketplace.isFetched && instance.isFetched, + placeholderData: keepPreviousData, + }); const [marketplaceAppsData, installedAppsData, privateAppsData] = marketplaceData || []; + useEffect(() => { + if (instance.data && marketplace.data) { + queryClient.invalidateQueries({ + queryKey: ['marketplace', 'apps-stored'], + }); + } + }, [marketplace.data, instance.data, queryClient]); + return ( { privateApps: getAppState(isMarketplaceDataLoading, privateAppsData), reload: async () => { - await Promise.all([queryClient.invalidateQueries(['marketplace'])]); + await Promise.all([ + queryClient.invalidateQueries({ + queryKey: ['marketplace'], + }), + ]); }, orchestrator: AppClientOrchestratorInstance, privateAppsEnabled: (limits?.privateApps?.max ?? 0) !== 0, diff --git a/apps/meteor/client/providers/OmnichannelProvider.tsx b/apps/meteor/client/providers/OmnichannelProvider.tsx index 487dfa475081..ed06c15d6873 100644 --- a/apps/meteor/client/providers/OmnichannelProvider.tsx +++ b/apps/meteor/client/providers/OmnichannelProvider.tsx @@ -78,9 +78,11 @@ const OmnichannelProvider = ({ children }: OmnichannelProviderProps) => { const { data: { priorities = [] } = {}, - isInitialLoading: isLoadingPriorities, + isLoading: isLoadingPriorities, isError: isErrorPriorities, - } = useQuery(['/v1/livechat/priorities'], () => getPriorities({ sort: JSON.stringify({ sortItem: 1 }) }), { + } = useQuery({ + queryKey: ['/v1/livechat/priorities'], + queryFn: () => getPriorities({ sort: JSON.stringify({ sortItem: 1 }) }), staleTime: Infinity, enabled: isPrioritiesEnabled, }); @@ -93,7 +95,9 @@ const OmnichannelProvider = ({ children }: OmnichannelProviderProps) => { } return subscribe('omnichannel.priority-changed', () => { - queryClient.invalidateQueries(['/v1/livechat/priorities']); + queryClient.invalidateQueries({ + queryKey: ['/v1/livechat/priorities'], + }); }); }, [isPrioritiesEnabled, queryClient, subscribe]); diff --git a/apps/meteor/client/providers/SettingsProvider.tsx b/apps/meteor/client/providers/SettingsProvider.tsx index 37959bcd78dc..e48af97ee398 100644 --- a/apps/meteor/client/providers/SettingsProvider.tsx +++ b/apps/meteor/client/providers/SettingsProvider.tsx @@ -1,12 +1,12 @@ import type { ISetting } from '@rocket.chat/core-typings'; import type { SettingsContextValue } from '@rocket.chat/ui-contexts'; import { SettingsContext, useAtLeastOnePermission, useMethod } from '@rocket.chat/ui-contexts'; +import { useQueryClient } from '@tanstack/react-query'; import { Tracker } from 'meteor/tracker'; import type { ReactNode } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { createReactiveSubscriptionFactory } from '../lib/createReactiveSubscriptionFactory'; -import { queryClient } from '../lib/queryClient'; import { PrivateSettingsCachedCollection } from '../lib/settings/PrivateSettingsCachedCollection'; import { PublicSettingsCachedCollection } from '../lib/settings/PublicSettingsCachedCollection'; @@ -89,18 +89,24 @@ const SettingsProvider = ({ children, privileged = false }: SettingsProviderProp [cachedCollection], ); - const settingsChangeCallback = (changes: { _id: string }[]): void => { - changes.forEach((val) => { - switch (val._id) { - case 'Enterprise_License': - queryClient.invalidateQueries(['licenses']); - break; - - default: - break; - } - }); - }; + const queryClient = useQueryClient(); + + // FIXME: This is a temporary solution to invalidate queries when settings change + const settingsChangeCallback = useCallback( + (changes: { _id: string }[]): void => { + changes.forEach((val) => { + switch (val._id) { + case 'Enterprise_License': + queryClient.invalidateQueries({ queryKey: ['licenses'] }); + break; + + default: + break; + } + }); + }, + [queryClient], + ); const saveSettings = useMethod('saveSettings'); const dispatch = useCallback( @@ -108,7 +114,7 @@ const SettingsProvider = ({ children, privileged = false }: SettingsProviderProp settingsChangeCallback(changes); await saveSettings(changes); }, - [saveSettings], + [saveSettings, settingsChangeCallback], ); const contextValue = useMemo( diff --git a/apps/meteor/client/providers/ToastMessagesProvider.tsx b/apps/meteor/client/providers/ToastMessagesProvider.tsx index c814106593d1..ba938f284e97 100644 --- a/apps/meteor/client/providers/ToastMessagesProvider.tsx +++ b/apps/meteor/client/providers/ToastMessagesProvider.tsx @@ -1,5 +1,7 @@ import { ToastBarProvider, useToastBarDispatch } from '@rocket.chat/fuselage-toastbar'; import { ToastMessagesContext } from '@rocket.chat/ui-contexts'; +import type { DefaultError, Query } from '@tanstack/react-query'; +import { useQueryClient } from '@tanstack/react-query'; import type { ReactNode } from 'react'; import { useEffect } from 'react'; @@ -17,6 +19,32 @@ type ToastMessageInnerProviderProps = { const ToastMessageInnerProvider = ({ children }: ToastMessageInnerProviderProps) => { const dispatchToastBar = useToastBarDispatch(); + const queryClient = useQueryClient(); + const queryCacheInstance = queryClient.getQueryCache(); + queryCacheInstance.config.onError = (error: DefaultError, query: Query) => { + const meta = query?.meta; + if (meta) { + const { errorToastMessage, apiErrorToastMessage } = meta as { + errorToastMessage?: string; + apiErrorToastMessage?: boolean; + }; + if (apiErrorToastMessage) { + dispatchToastMessage({ type: 'error', message: error }); + } else if (errorToastMessage) { + dispatchToastMessage({ type: 'error', message: errorToastMessage }); + } + } + }; + queryCacheInstance.config.onSuccess = (_, query: Query) => { + const meta = query?.meta; + if (meta) { + const { successToastMessage } = meta as { successToastMessage?: string }; + if (successToastMessage) { + dispatchToastMessage({ type: 'success', message: successToastMessage }); + } + } + }; + useEffect( () => subscribeToToastMessages(({ type, message, title = '' }) => { diff --git a/apps/meteor/client/providers/UserProvider/UserProvider.tsx b/apps/meteor/client/providers/UserProvider/UserProvider.tsx index 2e658e7e46b4..75f83f4edff0 100644 --- a/apps/meteor/client/providers/UserProvider/UserProvider.tsx +++ b/apps/meteor/client/providers/UserProvider/UserProvider.tsx @@ -2,6 +2,7 @@ import type { IRoom, ISubscription, IUser } from '@rocket.chat/core-typings'; import { useLocalStorage } from '@rocket.chat/fuselage-hooks'; import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; import { UserContext, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useQueryClient } from '@tanstack/react-query'; import { Meteor } from 'meteor/meteor'; import type { ContextType, ReactElement, ReactNode } from 'react'; import { useEffect, useMemo, useRef } from 'react'; @@ -16,7 +17,6 @@ import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { afterLogoutCleanUpCallback } from '../../../lib/callbacks/afterLogoutCleanUpCallback'; import { useReactiveValue } from '../../hooks/useReactiveValue'; import { createReactiveSubscriptionFactory } from '../../lib/createReactiveSubscriptionFactory'; -import { queryClient } from '../../lib/queryClient'; import { useCreateFontStyleElement } from '../../views/account/accessibility/hooks/useCreateFontStyleElement'; const getUser = (): IUser | null => Meteor.user() as IUser | null; @@ -94,13 +94,15 @@ const UserProvider = ({ children }: UserProviderProps): ReactElement => { } }, [preferedLanguage, setPreferedLanguage, setUserLanguage, user?.language, userLanguage, userId, setUserPreferences]); + const queryClient = useQueryClient(); + useEffect(() => { if (previousUserId.current && previousUserId.current !== userId) { queryClient.clear(); } previousUserId.current = userId; - }, [userId]); + }, [queryClient, userId]); return ; }; diff --git a/apps/meteor/client/sidebar/RoomMenu.tsx b/apps/meteor/client/sidebar/RoomMenu.tsx index 2e04f0cc9bec..afd2f573ae5a 100644 --- a/apps/meteor/client/sidebar/RoomMenu.tsx +++ b/apps/meteor/client/sidebar/RoomMenu.tsx @@ -131,7 +131,9 @@ const RoomMenu = ({ const handleToggleRead = useMutableCallback(async () => { try { - queryClient.invalidateQueries(['sidebar/search/spotlight']); + queryClient.invalidateQueries({ + queryKey: ['sidebar/search/spotlight'], + }); if (isUnread) { await readMessages({ rid, readThreads: true }); diff --git a/apps/meteor/client/sidebar/footer/SidebarFooterWatermark.tsx b/apps/meteor/client/sidebar/footer/SidebarFooterWatermark.tsx index 36a7657177c0..850f2160e1ad 100644 --- a/apps/meteor/client/sidebar/footer/SidebarFooterWatermark.tsx +++ b/apps/meteor/client/sidebar/footer/SidebarFooterWatermark.tsx @@ -21,7 +21,7 @@ export const SidebarFooterWatermark = (): ReactElement | null => { const license = response.data; - if (license.activeModules.includes('hide-watermark') && !license.trial) { + if (license?.activeModules.includes('hide-watermark') && !license.trial) { return null; } diff --git a/apps/meteor/client/sidebar/footer/voip/hooks/useOmnichannelContactLabel.ts b/apps/meteor/client/sidebar/footer/voip/hooks/useOmnichannelContactLabel.ts index 6b3d59830d1e..ded2b9021d78 100644 --- a/apps/meteor/client/sidebar/footer/voip/hooks/useOmnichannelContactLabel.ts +++ b/apps/meteor/client/sidebar/footer/voip/hooks/useOmnichannelContactLabel.ts @@ -8,7 +8,9 @@ export const useOmnichannelContactLabel = (caller: ICallerInfo): string => { const getContactBy = useEndpoint('GET', '/v1/omnichannel/contact.search'); const phone = parseOutboundPhoneNumber(caller.callerId); - const { data } = useQuery(['getContactsByPhone', phone], async () => getContactBy({ phone }).then(({ contact }) => contact), { + const { data } = useQuery({ + queryKey: ['getContactsByPhone', phone], + queryFn: async () => getContactBy({ phone }).then(({ contact }) => contact), enabled: !!phone, }); diff --git a/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx b/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx index c7c5f01b2c3c..39f81e02b8e9 100644 --- a/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx +++ b/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx @@ -24,35 +24,36 @@ const FederatedRoomList = ({ serverName, roomName, count }: FederatedRoomListPro const setModal = useSetModal(); const { t } = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); - const { data, isLoading, isFetchingNextPage, fetchNextPage } = useInfiniteFederationSearchPublicRooms(serverName, roomName, count); + const { data, isPending, isFetchingNextPage, fetchNextPage } = useInfiniteFederationSearchPublicRooms(serverName, roomName, count); - const { mutate: onClickJoin, isLoading: isLoadingMutation } = useMutation( - ['federation/joinExternalPublicRoom'], - async ({ id, pageToken }: IFederationPublicRooms) => + const { mutate: onClickJoin, isPending: isLoadingMutation } = useMutation({ + mutationKey: ['federation/joinExternalPublicRoom'], + + mutationFn: async ({ id, pageToken }: IFederationPublicRooms) => joinExternalPublicRoom({ externalRoomId: id as `!${string}:${string}`, roomName, pageToken }), - { - onSuccess: (_, data) => { - dispatchToastMessage({ - type: 'success', - message: t('Your_request_to_join__roomName__has_been_made_it_could_take_up_to_15_minutes_to_be_processed', { - roomName: data.name, - }), - }); + + onSuccess: (_, data) => { + dispatchToastMessage({ + type: 'success', + message: t('Your_request_to_join__roomName__has_been_made_it_could_take_up_to_15_minutes_to_be_processed', { + roomName: data.name, + }), + }); + setModal(null); + }, + + onError: (error, { id }) => { + if (error instanceof Error && error.message === 'already-joined') { setModal(null); - }, - onError: (error, { id }) => { - if (error instanceof Error && error.message === 'already-joined') { - setModal(null); - roomCoordinator.openRouteLink('c', { rid: id }); - return; - } + roomCoordinator.openRouteLink('c', { rid: id }); + return; + } - dispatchToastMessage({ type: 'error', message: error }); - }, + dispatchToastMessage({ type: 'error', message: error }); }, - ); + }); - if (isLoading) { + if (isPending) { return ; } @@ -69,7 +70,7 @@ const FederatedRoomList = ({ serverName, roomName, count }: FederatedRoomListPro Scroller: VirtuosoScrollbars, EmptyPlaceholder: FederatedRoomListEmptyPlaceholder, }} - endReached={isLoading || isFetchingNextPage ? () => undefined : () => fetchNextPage()} + endReached={isPending || isFetchingNextPage ? () => undefined : () => fetchNextPage()} itemContent={(_, room) => ( onClickJoin(room)} {...room} disabled={isLoadingMutation} key={room.id} /> )} diff --git a/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx b/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx index b3fc846a98bd..d9b02d3c31b1 100644 --- a/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx +++ b/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx @@ -37,13 +37,19 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer const { mutate: addServer, - isLoading, + isPending, isError, - } = useMutation(['v1/federation/addServerByUser', serverName], () => addMatrixServer({ serverName }), { + } = useMutation({ + mutationKey: ['v1/federation/addServerByUser', serverName], + mutationFn: () => addMatrixServer({ serverName }), + onSuccess: async () => { - await queryClient.invalidateQueries(['federation/listServersByUsers']); + await queryClient.invalidateQueries({ + queryKey: ['federation/listServersByUsers'], + }); setModal(); }, + onError: (error) => { const errorKey = getErrorKey(error); if (!errorKey) { @@ -54,7 +60,7 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer }, }); - const { data, isLoading: isLoadingServerList } = useMatrixServerList(); + const { data, isPending: isLoadingServerList } = useMatrixServerList(); const titleId = useUniqueId(); const serverNameId = useUniqueId(); @@ -71,7 +77,7 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer ) => { setServerName(e.currentTarget.value); @@ -81,7 +87,7 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer }} mie={4} /> - diff --git a/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx b/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx index 51a05f3f3b5a..db05da903c8d 100644 --- a/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx +++ b/apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx @@ -27,11 +27,15 @@ const MatrixFederationRemoveServerList = ({ servers }: MatrixFederationRemoveSer const queryClient = useQueryClient(); - const { mutate: removeServer, isLoading: isRemovingServer } = useMutation( - ['federation/removeServerByUser'], - (serverName: string) => removeMatrixServer({ serverName }), - { onSuccess: () => queryClient.invalidateQueries(['federation/listServersByUsers']) }, - ); + const { mutate: removeServer, isPending: isRemovingServer } = useMutation({ + mutationKey: ['federation/removeServerByUser'], + mutationFn: (serverName: string) => removeMatrixServer({ serverName }), + + onSuccess: () => + queryClient.invalidateQueries({ + queryKey: ['federation/listServersByUsers'], + }), + }); const t = useTranslation(); diff --git a/apps/meteor/client/sidebar/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.tsx b/apps/meteor/client/sidebar/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.tsx index 6d80a7a9b383..66336fe40058 100644 --- a/apps/meteor/client/sidebar/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.tsx +++ b/apps/meteor/client/sidebar/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.tsx @@ -5,14 +5,13 @@ const tenMinutes = 10 * 60 * 1000; export const useInfiniteFederationSearchPublicRooms = (serverName: string, roomName?: string, count?: number) => { const fetchRoomList = useEndpoint('GET', '/v1/federation/searchPublicRooms'); - return useInfiniteQuery( - ['federation/searchPublicRooms', serverName, roomName, count], - async ({ pageParam }) => fetchRoomList({ serverName, roomName, count, pageToken: pageParam }), - { - getNextPageParam: (lastPage) => lastPage.nextPageToken, - useErrorBoundary: true, - staleTime: tenMinutes, - cacheTime: tenMinutes, - }, - ); + return useInfiniteQuery({ + queryKey: ['federation/searchPublicRooms', serverName, roomName, count], + queryFn: async ({ pageParam }) => fetchRoomList({ serverName, roomName, count, pageToken: pageParam }), + getNextPageParam: (lastPage) => lastPage.nextPageToken, + initialPageParam: '', + throwOnError: true, + staleTime: tenMinutes, + gcTime: tenMinutes, + }); }; diff --git a/apps/meteor/client/sidebar/header/MatrixFederationSearch/useMatrixServerList.ts b/apps/meteor/client/sidebar/header/MatrixFederationSearch/useMatrixServerList.ts index 4f9ba64848f3..7ffa3d937bba 100644 --- a/apps/meteor/client/sidebar/header/MatrixFederationSearch/useMatrixServerList.ts +++ b/apps/meteor/client/sidebar/header/MatrixFederationSearch/useMatrixServerList.ts @@ -3,8 +3,10 @@ import { useQuery } from '@tanstack/react-query'; export const useMatrixServerList = () => { const fetchServerList = useEndpoint('GET', '/v1/federation/listServersByUser'); - return useQuery(['federation/listServersByUsers'], async () => fetchServerList(), { - useErrorBoundary: true, + return useQuery({ + queryKey: ['federation/listServersByUsers'], + queryFn: async () => fetchServerList(), + throwOnError: true, staleTime: Infinity, }); }; diff --git a/apps/meteor/client/sidebar/header/hooks/useVoipItemsSection.tsx b/apps/meteor/client/sidebar/header/hooks/useVoipItemsSection.tsx index e70df6d66055..c8b7e89dd229 100644 --- a/apps/meteor/client/sidebar/header/hooks/useVoipItemsSection.tsx +++ b/apps/meteor/client/sidebar/header/hooks/useVoipItemsSection.tsx @@ -40,12 +40,12 @@ export const useVoipItemsSection = (): { items: GenericMenuItemProps[] } | undef return t(clientError.message); } - if (!isReady || toggleVoip.isLoading) { + if (!isReady || toggleVoip.isPending) { return t('Loading'); } return ''; - }, [clientError, isReady, toggleVoip.isLoading, t]); + }, [clientError, isReady, toggleVoip.isPending, t]); return useMemo(() => { if (!isEnabled) { @@ -57,7 +57,7 @@ export const useVoipItemsSection = (): { items: GenericMenuItemProps[] } | undef { id: 'toggle-voip', icon: isRegistered ? 'phone-disabled' : 'phone', - disabled: !isReady || toggleVoip.isLoading, + disabled: !isReady || toggleVoip.isPending, onClick: () => toggleVoip.mutate(), content: ( diff --git a/apps/meteor/client/sidebar/search/SearchList.tsx b/apps/meteor/client/sidebar/search/SearchList.tsx index 1c9230bf942d..0d0f4c388d8e 100644 --- a/apps/meteor/client/sidebar/search/SearchList.tsx +++ b/apps/meteor/client/sidebar/search/SearchList.tsx @@ -100,9 +100,10 @@ const useSearchItems = (filterText: string): UseQueryResult<(ISubscription & IRo const getSpotlight = useMethod('spotlight'); - return useQuery( - ['sidebar/search/spotlight', name, usernamesFromClient, type, localRooms.map(({ _id, name }) => _id + name)], - async () => { + return useQuery({ + queryKey: ['sidebar/search/spotlight', name, usernamesFromClient, type, localRooms.map(({ _id, name }) => _id + name)], + + queryFn: async () => { if (localRooms.length === LIMIT) { return localRooms; } @@ -157,12 +158,10 @@ const useSearchItems = (filterText: string): UseQueryResult<(ISubscription & IRo const exact = resultsFromServer?.filter((item) => [item.name, item.fname].includes(name)); return Array.from(new Set([...exact, ...localRooms, ...resultsFromServer])); }, - { - staleTime: 60_000, - keepPreviousData: true, - placeholderData: localRooms, - }, - ); + + staleTime: 60_000, + placeholderData: (previousData) => previousData ?? localRooms, + }); }; const useInput = (initial: string): { value: string; onChange: FormEventHandler; setValue: Dispatch> } => { diff --git a/apps/meteor/client/sidebarv2/RoomMenu.tsx b/apps/meteor/client/sidebarv2/RoomMenu.tsx index af7de006dc42..f74a231c613f 100644 --- a/apps/meteor/client/sidebarv2/RoomMenu.tsx +++ b/apps/meteor/client/sidebarv2/RoomMenu.tsx @@ -131,7 +131,9 @@ const RoomMenu = ({ const handleToggleRead = useEffectEvent(async () => { try { - queryClient.invalidateQueries(['sidebar/search/spotlight']); + queryClient.invalidateQueries({ + queryKey: ['sidebar/search/spotlight'], + }); if (isUnread) { await readMessages({ rid, readThreads: true }); diff --git a/apps/meteor/client/sidebarv2/footer/SidebarFooterWatermark.tsx b/apps/meteor/client/sidebarv2/footer/SidebarFooterWatermark.tsx index 36a7657177c0..850f2160e1ad 100644 --- a/apps/meteor/client/sidebarv2/footer/SidebarFooterWatermark.tsx +++ b/apps/meteor/client/sidebarv2/footer/SidebarFooterWatermark.tsx @@ -21,7 +21,7 @@ export const SidebarFooterWatermark = (): ReactElement | null => { const license = response.data; - if (license.activeModules.includes('hide-watermark') && !license.trial) { + if (license?.activeModules.includes('hide-watermark') && !license.trial) { return null; } diff --git a/apps/meteor/client/sidebarv2/footer/voip/hooks/useOmnichannelContactLabel.ts b/apps/meteor/client/sidebarv2/footer/voip/hooks/useOmnichannelContactLabel.ts index 6b3d59830d1e..ded2b9021d78 100644 --- a/apps/meteor/client/sidebarv2/footer/voip/hooks/useOmnichannelContactLabel.ts +++ b/apps/meteor/client/sidebarv2/footer/voip/hooks/useOmnichannelContactLabel.ts @@ -8,7 +8,9 @@ export const useOmnichannelContactLabel = (caller: ICallerInfo): string => { const getContactBy = useEndpoint('GET', '/v1/omnichannel/contact.search'); const phone = parseOutboundPhoneNumber(caller.callerId); - const { data } = useQuery(['getContactsByPhone', phone], async () => getContactBy({ phone }).then(({ contact }) => contact), { + const { data } = useQuery({ + queryKey: ['getContactsByPhone', phone], + queryFn: async () => getContactBy({ phone }).then(({ contact }) => contact), enabled: !!phone, }); diff --git a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx index 50f2fa007088..50bdb8018486 100644 --- a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx +++ b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx @@ -24,36 +24,37 @@ const FederatedRoomList = ({ serverName, roomName, count }: FederatedRoomListPro const setModal = useSetModal(); const { t } = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); - const { data, isLoading, isFetchingNextPage, fetchNextPage } = useInfiniteFederationSearchPublicRooms(serverName, roomName, count); + const { data, isPending, isFetchingNextPage, fetchNextPage } = useInfiniteFederationSearchPublicRooms(serverName, roomName, count); - const { mutate: onClickJoin, isLoading: isLoadingMutation } = useMutation( - ['federation/joinExternalPublicRoom'], - async ({ id, pageToken }: IFederationPublicRooms) => { + const { mutate: onClickJoin, isPending: isLoadingMutation } = useMutation({ + mutationKey: ['federation/joinExternalPublicRoom'], + + mutationFn: async ({ id, pageToken }: IFederationPublicRooms) => { return joinExternalPublicRoom({ externalRoomId: id as `!${string}:${string}`, roomName, pageToken }); }, - { - onSuccess: (_, data) => { - dispatchToastMessage({ - type: 'success', - message: t('Your_request_to_join__roomName__has_been_made_it_could_take_up_to_15_minutes_to_be_processed', { - roomName: data.name, - }), - }); + + onSuccess: (_, data) => { + dispatchToastMessage({ + type: 'success', + message: t('Your_request_to_join__roomName__has_been_made_it_could_take_up_to_15_minutes_to_be_processed', { + roomName: data.name, + }), + }); + setModal(null); + }, + + onError: (error, { id }) => { + if (error instanceof Error && error.message === 'already-joined') { setModal(null); - }, - onError: (error, { id }) => { - if (error instanceof Error && error.message === 'already-joined') { - setModal(null); - roomCoordinator.openRouteLink('c', { rid: id }); - return; - } + roomCoordinator.openRouteLink('c', { rid: id }); + return; + } - dispatchToastMessage({ type: 'error', message: error }); - }, + dispatchToastMessage({ type: 'error', message: error }); }, - ); + }); - if (isLoading) { + if (isPending) { return ; } @@ -70,7 +71,7 @@ const FederatedRoomList = ({ serverName, roomName, count }: FederatedRoomListPro Scroller: VirtuosoScrollbars, EmptyPlaceholder: FederatedRoomListEmptyPlaceholder, }} - endReached={isLoading || isFetchingNextPage ? () => undefined : () => fetchNextPage()} + endReached={isPending || isFetchingNextPage ? () => undefined : () => fetchNextPage()} itemContent={(_, room) => ( onClickJoin(room)} {...room} disabled={isLoadingMutation} key={room.id} /> )} diff --git a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx index 13a761c0cac6..dd0d15e11131 100644 --- a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx +++ b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationManageServerModal.tsx @@ -36,13 +36,19 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer const { mutate: addServer, - isLoading, + isPending, isError, - } = useMutation(['v1/federation/addServerByUser', serverName], () => addMatrixServer({ serverName }), { + } = useMutation({ + mutationKey: ['v1/federation/addServerByUser', serverName], + mutationFn: () => addMatrixServer({ serverName }), + onSuccess: async () => { - await queryClient.invalidateQueries(['federation/listServersByUsers']); + await queryClient.invalidateQueries({ + queryKey: ['federation/listServersByUsers'], + }); setModal(); }, + onError: (error) => { const errorKey = getErrorKey(error); if (!errorKey) { @@ -53,7 +59,7 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer }, }); - const { data, isLoading: isLoadingServerList } = useMatrixServerList(); + const { data, isPending: isLoadingServerList } = useMatrixServerList(); return ( @@ -66,7 +72,7 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer {t('Server_name')} ) => { setServerName(e.currentTarget.value); @@ -76,7 +82,7 @@ const MatrixFederationAddServerModal = ({ onClickClose }: MatrixFederationAddSer }} mie={4} /> - diff --git a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx index 073d7976ca94..2531be96e6f0 100644 --- a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx +++ b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/MatrixFederationRemoveServerList.tsx @@ -27,11 +27,15 @@ const MatrixFederationRemoveServerList = ({ servers }: MatrixFederationRemoveSer const queryClient = useQueryClient(); - const { mutate: removeServer, isLoading: isRemovingServer } = useMutation( - ['federation/removeServerByUser'], - (serverName: string) => removeMatrixServer({ serverName }), - { onSuccess: () => queryClient.invalidateQueries(['federation/listServersByUsers']) }, - ); + const { mutate: removeServer, isPending: isRemovingServer } = useMutation({ + mutationKey: ['federation/removeServerByUser'], + mutationFn: (serverName: string) => removeMatrixServer({ serverName }), + + onSuccess: () => + queryClient.invalidateQueries({ + queryKey: ['federation/listServersByUsers'], + }), + }); const t = useTranslation(); diff --git a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.ts b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.ts index 6d80a7a9b383..66336fe40058 100644 --- a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.ts +++ b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useInfiniteFederationSearchPublicRooms.ts @@ -5,14 +5,13 @@ const tenMinutes = 10 * 60 * 1000; export const useInfiniteFederationSearchPublicRooms = (serverName: string, roomName?: string, count?: number) => { const fetchRoomList = useEndpoint('GET', '/v1/federation/searchPublicRooms'); - return useInfiniteQuery( - ['federation/searchPublicRooms', serverName, roomName, count], - async ({ pageParam }) => fetchRoomList({ serverName, roomName, count, pageToken: pageParam }), - { - getNextPageParam: (lastPage) => lastPage.nextPageToken, - useErrorBoundary: true, - staleTime: tenMinutes, - cacheTime: tenMinutes, - }, - ); + return useInfiniteQuery({ + queryKey: ['federation/searchPublicRooms', serverName, roomName, count], + queryFn: async ({ pageParam }) => fetchRoomList({ serverName, roomName, count, pageToken: pageParam }), + getNextPageParam: (lastPage) => lastPage.nextPageToken, + initialPageParam: '', + throwOnError: true, + staleTime: tenMinutes, + gcTime: tenMinutes, + }); }; diff --git a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useMatrixServerList.ts b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useMatrixServerList.ts index 4f9ba64848f3..7ffa3d937bba 100644 --- a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useMatrixServerList.ts +++ b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/useMatrixServerList.ts @@ -3,8 +3,10 @@ import { useQuery } from '@tanstack/react-query'; export const useMatrixServerList = () => { const fetchServerList = useEndpoint('GET', '/v1/federation/listServersByUser'); - return useQuery(['federation/listServersByUsers'], async () => fetchServerList(), { - useErrorBoundary: true, + return useQuery({ + queryKey: ['federation/listServersByUsers'], + queryFn: async () => fetchServerList(), + throwOnError: true, staleTime: Infinity, }); }; diff --git a/apps/meteor/client/sidebarv2/header/hooks/useSearchItems.ts b/apps/meteor/client/sidebarv2/header/hooks/useSearchItems.ts index cc7bf02249b7..a44dceeb2f8f 100644 --- a/apps/meteor/client/sidebarv2/header/hooks/useSearchItems.ts +++ b/apps/meteor/client/sidebarv2/header/hooks/useSearchItems.ts @@ -16,6 +16,7 @@ const options = { limit: LIMIT, } as const; +// FIXME: the return type is UTTERLY wrong, but I'm not sure what it should be export const useSearchItems = (filterText: string): UseQueryResult => { const [, mention, name] = useMemo(() => filterText.match(/(@|#)?(.*)/i) || [], [filterText]); const query = useMemo(() => { @@ -48,9 +49,10 @@ export const useSearchItems = (filterText: string): UseQueryResult _id + name)], - async () => { + return useQuery({ + queryKey: ['sidebar/search/spotlight', name, usernamesFromClient, type, localRooms.map(({ _id, name }) => _id + name)], + + queryFn: async () => { if (localRooms.length === LIMIT) { return localRooms; } @@ -105,10 +107,8 @@ export const useSearchItems = (filterText: string): UseQueryResult [item.name, item.fname].includes(name)); return Array.from(new Set([...exact, ...localRooms, ...resultsFromServer])); }, - { - staleTime: 60_000, - keepPreviousData: true, - placeholderData: localRooms, - }, - ); + + staleTime: 60_000, + placeholderData: (previousData) => previousData ?? localRooms, + }); }; diff --git a/apps/meteor/client/stories/contexts/QueryClientProviderMock.tsx b/apps/meteor/client/stories/contexts/QueryClientProviderMock.tsx index cb16201e3a21..b1cecf148ade 100644 --- a/apps/meteor/client/stories/contexts/QueryClientProviderMock.tsx +++ b/apps/meteor/client/stories/contexts/QueryClientProviderMock.tsx @@ -1,25 +1,43 @@ -import { QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import type { DefaultError, Query } from '@tanstack/react-query'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { ReactNode } from 'react'; -const queryCache = new QueryCache(); +import { dispatchToastMessage } from '../../lib/toast'; const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, - cacheTime: Infinity, + gcTime: Infinity, refetchOnWindowFocus: false, }, }, - queryCache, }); type QueryClientProviderMockProps = { children?: ReactNode; }; -const QueryClientProviderMock = ({ children }: QueryClientProviderMockProps) => ( - {children} -); +const QueryClientProviderMock = ({ children }: QueryClientProviderMockProps) => { + const queryCacheInstance = queryClient.getQueryCache(); + + queryCacheInstance.config.onError = (error: DefaultError, query: Query) => { + const { errorToastMessage, apiErrorToastMessage } = query?.meta as { errorToastMessage?: string; apiErrorToastMessage?: boolean }; + if (apiErrorToastMessage) { + dispatchToastMessage({ type: 'error', message: error }); + } else if (errorToastMessage) { + dispatchToastMessage({ type: 'error', message: errorToastMessage }); + } + }; + + queryCacheInstance.config.onSuccess = (_, query: Query) => { + const { successToastMessage } = query?.meta as { successToastMessage?: string }; + if (successToastMessage) { + dispatchToastMessage({ type: 'success', message: successToastMessage }); + } + }; + + return {children}; +}; export default QueryClientProviderMock; diff --git a/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx b/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx index 5d486c28cb3d..66829705f5b7 100644 --- a/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx +++ b/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx @@ -58,7 +58,10 @@ const CustomEmoji = ({ onClick, reload }: CustomEmojiProps) => { ); const getEmojiList = useEndpoint('GET', '/v1/emoji-custom.all'); - const { data, refetch, isSuccess, isLoading, isError } = useQuery(['getEmojiList', query], () => getEmojiList(query)); + const { data, refetch, isSuccess, isLoading, isError } = useQuery({ + queryKey: ['getEmojiList', query], + queryFn: () => getEmojiList(query), + }); useEffect(() => { reload.current = refetch; diff --git a/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx b/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx index 72801a373aea..a593e67333c7 100644 --- a/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx +++ b/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx @@ -19,12 +19,16 @@ const EditCustomEmojiWithData = ({ _id, onChange, close, ...props }: EditCustomE const getEmojis = useEndpoint('GET', '/v1/emoji-custom.list'); - const { data, isLoading, error, refetch } = useQuery(['custom-emojis', query], async () => { - const emoji = await getEmojis(query); - return emoji; + const { data, isPending, error, refetch } = useQuery({ + queryKey: ['custom-emojis', query], + + queryFn: async () => { + const emoji = await getEmojis(query); + return emoji; + }, }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx b/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx index 91e988e0acbf..7a70ec984815 100644 --- a/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx +++ b/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx @@ -44,7 +44,9 @@ const CustomSoundsTable = ({ reload, onClick }: CustomSoundsTableProps) => { ); const getSounds = useEndpoint('GET', '/v1/custom-sounds.list'); - const { data, refetch, isLoading, isError, isSuccess } = useQuery(['custom-sounds', query], async () => getSounds(query), { + const { data, refetch, isLoading, isError, isSuccess } = useQuery({ + queryKey: ['custom-sounds', query], + queryFn: async () => getSounds(query), refetchOnMount: false, }); diff --git a/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx b/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx index 5eabbaa5e8cf..a16c6e476505 100644 --- a/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx +++ b/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx @@ -1,4 +1,4 @@ -import { useEndpoint, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import { useTranslation } from 'react-i18next'; @@ -16,11 +16,10 @@ function EditCustomSound({ _id, onChange, ...props }: EditCustomSoundProps): Rea const { t } = useTranslation(); const getSounds = useEndpoint('GET', '/v1/custom-sounds.list'); - const dispatchToastMessage = useToastMessageDispatch(); + const { data, isPending, refetch } = useQuery({ + queryKey: ['custom-sounds', _id], - const { data, isLoading, refetch } = useQuery( - ['custom-sounds', _id], - async () => { + queryFn: async () => { const { sounds } = await getSounds({ query: JSON.stringify({ _id }) }); if (sounds.length === 0) { @@ -28,14 +27,10 @@ function EditCustomSound({ _id, onChange, ...props }: EditCustomSoundProps): Rea } return sounds[0]; }, - { - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); - }, - }, - ); + meta: { apiErrorToastMessage: true }, + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserActiveConnections.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserActiveConnections.tsx index 71c838435169..f82714f367d2 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserActiveConnections.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserActiveConnections.tsx @@ -8,7 +8,7 @@ const CustomUserActiveConnections = () => { const result = useActiveConnections(); - if (result.isLoading || result.isError) { + if (result.isPending || result.isError) { return ; } diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx index a9f42b7f8680..d033bb303ba4 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx @@ -21,9 +21,13 @@ const CustomUserStatusFormWithData = ({ _id, onReload, onClose }: CustomUserStat const getCustomUserStatus = useEndpoint('GET', '/v1/custom-user-status.list'); - const { data, isLoading, error, refetch } = useQuery(['custom-user-statuses', query], async () => { - const customUserStatus = await getCustomUserStatus(query); - return customUserStatus; + const { data, isPending, error, refetch } = useQuery({ + queryKey: ['custom-user-statuses', query], + + queryFn: async () => { + const customUserStatus = await getCustomUserStatus(query); + return customUserStatus; + }, }); const handleReload = (): void => { @@ -35,7 +39,7 @@ const CustomUserStatusFormWithData = ({ _id, onReload, onClose }: CustomUserStat return ; } - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusService.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusService.tsx index aadc9434c96f..21ef3e0e94c1 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusService.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusService.tsx @@ -24,10 +24,12 @@ const CustomUserStatusService = () => { const result = useActiveConnections(); const presenceDisabled = useSetting('Presence_broadcast_disabled', false); const togglePresenceServiceEndpoint = useEndpoint('POST', '/v1/presence.enableBroadcast'); - const disablePresenceService = useMutation(() => togglePresenceServiceEndpoint()); - const { data: license, isLoading: licenseIsLoading } = useIsEnterprise(); + const disablePresenceService = useMutation({ + mutationFn: () => togglePresenceServiceEndpoint(), + }); + const { data: license, isPending: licenseIsLoading } = useIsEnterprise(); - if (result.isLoading || disablePresenceService.isLoading || licenseIsLoading) { + if (result.isPending || disablePresenceService.isPending || licenseIsLoading) { return ( @@ -59,7 +61,7 @@ const CustomUserStatusService = () => { {t('Service_status')} disablePresenceService.mutate()} /> diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx index ac118649e1a7..0c7b3223902c 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx @@ -1,7 +1,7 @@ import { Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { escapeRegExp } from '@rocket.chat/string-helpers'; -import { useEndpoint, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactElement, MutableRefObject } from 'react'; import { useState, useMemo, useEffect } from 'react'; @@ -46,20 +46,18 @@ const CustomUserStatus = ({ reload, onClick }: CustomUserStatusProps): ReactElem ); const getCustomUserStatus = useEndpoint('GET', '/v1/custom-user-status.list'); - const dispatchToastMessage = useToastMessageDispatch(); - const { data, isLoading, refetch, isFetched } = useQuery( - ['custom-user-statuses', query], - async () => { + const { data, isLoading, refetch, isFetched } = useQuery({ + queryKey: ['custom-user-statuses', query], + + queryFn: async () => { const { statuses } = await getCustomUserStatus(query); return statuses; }, - { - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); - }, + meta: { + apiErrorToastMessage: true, }, - ); + }); useEffect(() => { reload.current = refetch; diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx b/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx index 17257e54999f..b70c6a85f32b 100644 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx @@ -10,9 +10,12 @@ import { FormSkeleton } from '../../../components/Skeleton'; const EmailInboxFormWithData = ({ id }: { id: IEmailInbox['_id'] }): ReactElement => { const t = useTranslation(); const getEmailInboxById = useEndpoint('GET', '/v1/email-inbox/:_id', { _id: id }); - const { data, isLoading, error } = useQuery(['email-inbox', id], () => getEmailInboxById()); + const { data, isPending, error } = useQuery({ + queryKey: ['email-inbox', id], + queryFn: () => getEmailInboxById(), + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx b/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx index 5ffc6e4f2d13..29cf66557e31 100644 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx @@ -42,7 +42,10 @@ const EmailInboxTable = (): ReactElement => { ...(current && { offset: current }), }; - const result = useQuery(['email-list', query], () => endpoint(query)); + const result = useQuery({ + queryKey: ['email-list', query], + queryFn: () => endpoint(query), + }); const headers = useMemo( () => [ @@ -62,7 +65,7 @@ const EmailInboxTable = (): ReactElement => { return ( <> - {result.isLoading && ( + {result.isPending && ( {headers} diff --git a/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts b/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts index 875f9c2d932d..571786b39ce4 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts @@ -1,5 +1,5 @@ import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { Period } from '../../../../components/dashboards/periods'; import { getPeriodRange } from '../../../../components/dashboards/periods'; @@ -14,9 +14,10 @@ type UseChannelsListOptions = { export const useChannelsList = ({ period, offset, count }: UseChannelsListOptions) => { const getChannelsList = useEndpoint('GET', '/v1/engagement-dashboard/channels/list'); - return useQuery( - ['admin/engagement-dashboard/channels/list', { period, offset, count }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/channels/list', { period, offset, count }], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getChannelsList({ @@ -35,10 +36,9 @@ export const useChannelsList = ({ period, offset, count }: UseChannelsListOption } : undefined; }, - { - keepPreviousData: true, - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + placeholderData: keepPreviousData, + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/messages/useMessageOrigins.ts b/apps/meteor/client/views/admin/engagementDashboard/messages/useMessageOrigins.ts index e4e9526b571f..b451840427cd 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/messages/useMessageOrigins.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/messages/useMessageOrigins.ts @@ -10,9 +10,10 @@ type UseMessageOriginsOptions = { period: Period['key'] }; export const useMessageOrigins = ({ period }: UseMessageOriginsOptions) => { const getMessageOrigins = useEndpoint('GET', '/v1/engagement-dashboard/messages/origin'); - return useQuery( - ['admin/engagement-dashboard/messages/origins', { period }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/messages/origins', { period }], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getMessageOrigins({ @@ -28,9 +29,8 @@ export const useMessageOrigins = ({ period }: UseMessageOriginsOptions) => { } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/messages/useMessagesSent.ts b/apps/meteor/client/views/admin/engagementDashboard/messages/useMessagesSent.ts index daeeaa388f58..2f3ab1647cfa 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/messages/useMessagesSent.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/messages/useMessagesSent.ts @@ -10,9 +10,10 @@ type UseMessagesSentOptions = { period: Period['key'] }; export const useMessagesSent = ({ period }: UseMessagesSentOptions) => { const getMessagesSent = useEndpoint('GET', '/v1/engagement-dashboard/messages/messages-sent'); - return useQuery( - ['admin/engagement-dashboard/messages/messages-sent', { period }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/messages/messages-sent', { period }], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getMessagesSent({ @@ -28,9 +29,8 @@ export const useMessagesSent = ({ period }: UseMessagesSentOptions) => { } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/messages/useTopFivePopularChannels.ts b/apps/meteor/client/views/admin/engagementDashboard/messages/useTopFivePopularChannels.ts index d7566d3df6fb..bc6780a3e127 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/messages/useTopFivePopularChannels.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/messages/useTopFivePopularChannels.ts @@ -10,9 +10,10 @@ type UseTopFivePopularChannelsOptions = { period: Period['key'] }; export const useTopFivePopularChannels = ({ period }: UseTopFivePopularChannelsOptions) => { const getTopFivePopularChannels = useEndpoint('GET', '/v1/engagement-dashboard/messages/top-five-popular-channels'); - return useQuery( - ['admin/engagement-dashboard/messages/top-five-popular-channels', { period }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/messages/top-five-popular-channels', { period }], + + queryFn: async () => { const { start, end } = getPeriodRange(period); const response = await getTopFivePopularChannels({ @@ -28,9 +29,8 @@ export const useTopFivePopularChannels = ({ period }: UseTopFivePopularChannelsO } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/UsersByTimeOfTheDaySection.tsx b/apps/meteor/client/views/admin/engagementDashboard/users/UsersByTimeOfTheDaySection.tsx index 7c266542816c..aa1ea2103423 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/UsersByTimeOfTheDaySection.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/users/UsersByTimeOfTheDaySection.tsx @@ -22,12 +22,12 @@ const UsersByTimeOfTheDaySection = ({ timezone }: UsersByTimeOfTheDaySectionProp const utc = timezone === 'utc'; - const { data, isLoading } = useUsersByTimeOfTheDay({ period, utc }); + const { data, isPending } = useUsersByTimeOfTheDay({ period, utc }); const { t } = useTranslation(); const [dates, values] = useMemo(() => { - if (!data || isLoading) { + if (!data || isPending) { return []; } @@ -61,7 +61,7 @@ const UsersByTimeOfTheDaySection = ({ timezone }: UsersByTimeOfTheDaySectionProp } return [dates, values]; - }, [data, isLoading, utc]); + }, [data, isPending, utc]); const tooltip = useCallback( ({ cell }: { cell: ComputedCell }) => { @@ -99,7 +99,7 @@ const UsersByTimeOfTheDaySection = ({ timezone }: UsersByTimeOfTheDaySectionProp /> - {!isLoading && values && dates ? ( + {!isPending && values && dates ? ( diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/useActiveUsers.ts b/apps/meteor/client/views/admin/engagementDashboard/users/useActiveUsers.ts index 345540a08e1f..cb5c7d693904 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/useActiveUsers.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/users/useActiveUsers.ts @@ -9,9 +9,10 @@ type UseActiveUsersOptions = { utc: boolean }; export const useActiveUsers = ({ utc }: UseActiveUsersOptions) => { const getActiveUsers = useEndpoint('GET', '/v1/engagement-dashboard/users/active-users'); - return useQuery( - ['admin/engagement-dashboard/users/active', { utc }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/users/active', { utc }], + + queryFn: async () => { const { start, end } = getPeriodRange('last 30 days', utc); const response = await getActiveUsers({ @@ -27,9 +28,8 @@ export const useActiveUsers = ({ utc }: UseActiveUsersOptions) => { } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/useHourlyChatActivity.ts b/apps/meteor/client/views/admin/engagementDashboard/users/useHourlyChatActivity.ts index f2a7b98ebc41..98cdcc6818f8 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/useHourlyChatActivity.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/users/useHourlyChatActivity.ts @@ -11,9 +11,10 @@ type UseHourlyChatActivityOptions = { export const useHourlyChatActivity = ({ displacement, utc }: UseHourlyChatActivityOptions) => { const getHourlyChatActivity = useEndpoint('GET', '/v1/engagement-dashboard/users/chat-busier/hourly-data'); - return useQuery( - ['admin/engagement-dashboard/users/hourly-chat-activity', { displacement, utc }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/users/hourly-chat-activity', { displacement, utc }], + + queryFn: async () => { const day = (utc ? moment.utc().endOf('day') : moment().endOf('day')).subtract(displacement, 'days').toDate(); const response = await getHourlyChatActivity({ @@ -27,9 +28,8 @@ export const useHourlyChatActivity = ({ displacement, utc }: UseHourlyChatActivi } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/useNewUsers.ts b/apps/meteor/client/views/admin/engagementDashboard/users/useNewUsers.ts index 1d378dc77b49..10dcbfd96cce 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/useNewUsers.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/users/useNewUsers.ts @@ -7,9 +7,10 @@ import { getPeriodRange } from '../../../../components/dashboards/periods'; export const useNewUsers = ({ period, utc }: { period: Period['key']; utc: boolean }) => { const getNewUsers = useEndpoint('GET', '/v1/engagement-dashboard/users/new-users'); - return useQuery( - ['admin/engagement-dashboard/users/new', { period, utc }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/users/new', { period, utc }], + + queryFn: async () => { const { start, end } = getPeriodRange(period, utc); const response = await getNewUsers({ @@ -25,9 +26,8 @@ export const useNewUsers = ({ period, utc }: { period: Period['key']; utc: boole } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/useUsersByTimeOfTheDay.ts b/apps/meteor/client/views/admin/engagementDashboard/users/useUsersByTimeOfTheDay.ts index 6a9fa7897814..4118edce0f1c 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/useUsersByTimeOfTheDay.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/users/useUsersByTimeOfTheDay.ts @@ -10,9 +10,10 @@ type UseUsersByTimeOfTheDayOptions = { period: Period['key']; utc: boolean }; export const useUsersByTimeOfTheDay = ({ period, utc }: UseUsersByTimeOfTheDayOptions) => { const getUsersByTimeOfTheDay = useEndpoint('GET', '/v1/engagement-dashboard/users/users-by-time-of-the-day-in-a-week'); - return useQuery( - ['admin/engagement-dashboard/users/users-by-time-of-the-day', { period, utc }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/users/users-by-time-of-the-day', { period, utc }], + + queryFn: async () => { const { start, end } = getPeriodRange(period, utc); const response = await getUsersByTimeOfTheDay({ @@ -28,9 +29,8 @@ export const useUsersByTimeOfTheDay = ({ period, utc }: UseUsersByTimeOfTheDayOp } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/useWeeklyChatActivity.ts b/apps/meteor/client/views/admin/engagementDashboard/users/useWeeklyChatActivity.ts index 50b6667d535b..6f9c0bde042d 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/useWeeklyChatActivity.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/users/useWeeklyChatActivity.ts @@ -11,9 +11,10 @@ type UseWeeklyChatActivityOptions = { export const useWeeklyChatActivity = ({ displacement, utc }: UseWeeklyChatActivityOptions) => { const getWeeklyChatActivity = useEndpoint('GET', '/v1/engagement-dashboard/users/chat-busier/weekly-data'); - return useQuery( - ['admin/engagement-dashboard/users/weekly-chat-activity', { displacement, utc }], - async () => { + return useQuery({ + queryKey: ['admin/engagement-dashboard/users/weekly-chat-activity', { displacement, utc }], + + queryFn: async () => { const day = (utc ? moment.utc().endOf('day') : moment().endOf('day')).subtract(displacement, 'weeks').toDate(); const response = await getWeeklyChatActivity({ @@ -27,9 +28,8 @@ export const useWeeklyChatActivity = ({ displacement, utc }: UseWeeklyChatActivi } : undefined; }, - { - refetchInterval: 5 * 60 * 1000, - useErrorBoundary: true, - }, - ); + + refetchInterval: 5 * 60 * 1000, + throwOnError: true, + }); }; diff --git a/apps/meteor/client/views/admin/federationDashboard/OverviewSection.tsx b/apps/meteor/client/views/admin/federationDashboard/OverviewSection.tsx index f827512f0c0a..9275247c9ff4 100644 --- a/apps/meteor/client/views/admin/federationDashboard/OverviewSection.tsx +++ b/apps/meteor/client/views/admin/federationDashboard/OverviewSection.tsx @@ -9,11 +9,13 @@ import CounterSet from '../../../components/dataView/CounterSet'; const useOverviewData = (): [eventCount: ReactNode, userCount: ReactNode, serverCount: ReactNode] => { const getFederationOverviewData = useMethod('federation:getOverviewData'); - const result = useQuery(['admin/federation-dashboard/overview'], async () => getFederationOverviewData(), { + const result = useQuery({ + queryKey: ['admin/federation-dashboard/overview'], + queryFn: async () => getFederationOverviewData(), refetchInterval: 10_000, }); - if (result.isLoading) { + if (result.isPending) { return [ , , diff --git a/apps/meteor/client/views/admin/federationDashboard/ServersSection.tsx b/apps/meteor/client/views/admin/federationDashboard/ServersSection.tsx index 6bf480c4d394..d00283e0d1ce 100644 --- a/apps/meteor/client/views/admin/federationDashboard/ServersSection.tsx +++ b/apps/meteor/client/views/admin/federationDashboard/ServersSection.tsx @@ -6,11 +6,13 @@ import type { ReactElement } from 'react'; function ServersSection(): ReactElement | null { const getFederationServers = useMethod('federation:getServers'); - const result = useQuery(['admin/federation-dashboard/servers'], async () => getFederationServers(), { + const result = useQuery({ + queryKey: ['admin/federation-dashboard/servers'], + queryFn: async () => getFederationServers(), refetchInterval: 10_000, }); - if (result.isLoading) { + if (result.isPending) { return ; } diff --git a/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx b/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx index 0a12ca1f6aba..8cffb3868b82 100644 --- a/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx +++ b/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx @@ -23,29 +23,29 @@ function ImportHistoryPage() { const router = useRouter(); - const currentOperation = useQuery( - ['ImportHistoryPage', 'currentOperation'], - async () => { + const currentOperation = useQuery({ + queryKey: ['ImportHistoryPage', 'currentOperation'], + queryFn: async () => { const { operation = { valid: false } } = await getCurrentImportOperation(); return operation; }, - { - onError: () => dispatchToastMessage({ type: 'error', message: t('Failed_To_Load_Import_Operation') }), + meta: { + errorToastMessage: t('Failed_To_Load_Import_Operation'), }, - ); + }); - const latestOperations = useQuery( - ['ImportHistoryPage', 'latestOperations'], - async () => { + const latestOperations = useQuery({ + queryKey: ['ImportHistoryPage', 'latestOperations'], + queryFn: async () => { const operations = await getLatestImportOperations(); return operations; }, - { - onError: () => dispatchToastMessage({ type: 'error', message: t('Failed_To_Load_Import_History') }), + meta: { + errorToastMessage: t('Failed_To_Load_Import_History'), }, - ); + }); - const isLoading = currentOperation.isLoading || latestOperations.isLoading; + const isLoading = currentOperation.isPending || latestOperations.isPending; const hasAnySuccessfulImport = useMemo(() => { return latestOperations.isSuccess && latestOperations.data.some(({ status }) => status === ProgressStep.DONE); @@ -62,8 +62,12 @@ function ImportHistoryPage() { dispatchToastMessage({ type: 'error', message: t('Failed_To_Download_Files') }); }, onSuccess: ({ count }) => { - queryClient.invalidateQueries(['ImportHistoryPage', 'currentOperation']); - queryClient.invalidateQueries(['ImportHistoryPage', 'latestOperations']); + queryClient.invalidateQueries({ + queryKey: ['ImportHistoryPage', 'currentOperation'], + }); + queryClient.invalidateQueries({ + queryKey: ['ImportHistoryPage', 'latestOperations'], + }); if (!count) { dispatchToastMessage({ type: 'info', message: t('No_files_left_to_download') }); return; @@ -81,8 +85,12 @@ function ImportHistoryPage() { dispatchToastMessage({ type: 'error', message: t('Failed_To_Download_Files') }); }, onSuccess: ({ count }) => { - queryClient.invalidateQueries(['ImportHistoryPage', 'currentOperation']); - queryClient.invalidateQueries(['ImportHistoryPage', 'latestOperations']); + queryClient.invalidateQueries({ + queryKey: ['ImportHistoryPage', 'currentOperation'], + }); + queryClient.invalidateQueries({ + queryKey: ['ImportHistoryPage', 'latestOperations'], + }); if (!count) { dispatchToastMessage({ type: 'info', message: t('No_files_left_to_download') }); return; @@ -104,8 +112,8 @@ function ImportHistoryPage() { {hasAnySuccessfulImport && ( )} @@ -120,7 +120,7 @@ const SubscriptionPage = () => { )} - {(showSubscriptionCallout || syncLicenseUpdate.isLoading) && ( + {(showSubscriptionCallout || syncLicenseUpdate.isPending) && ( {t('Sync_license_update_Callout')} diff --git a/apps/meteor/client/views/admin/subscription/components/cards/ActiveSessionsCard.tsx b/apps/meteor/client/views/admin/subscription/components/cards/ActiveSessionsCard.tsx index 896c1961090a..ca7a229ae329 100644 --- a/apps/meteor/client/views/admin/subscription/components/cards/ActiveSessionsCard.tsx +++ b/apps/meteor/client/views/admin/subscription/components/cards/ActiveSessionsCard.tsx @@ -32,7 +32,7 @@ const ActiveSessionsCard = (): ReactElement => { infoText: t('ActiveSessions_InfoText'), }; - if (result.isLoading || result.isError) { + if (result.isPending || result.isError) { return ( diff --git a/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.tsx b/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.tsx index e244a1c5b5a9..c2de4cd6b02a 100644 --- a/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.tsx +++ b/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.tsx @@ -23,6 +23,6 @@ export const useCancelSubscriptionModal = () => { return { open, - isLoading: removeLicense.isLoading, + isLoading: removeLicense.isPending, }; }; diff --git a/apps/meteor/client/views/admin/users/AdminUserForm.tsx b/apps/meteor/client/views/admin/users/AdminUserForm.tsx index 61308bff2fab..1e7667c40816 100644 --- a/apps/meteor/client/views/admin/users/AdminUserForm.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserForm.tsx @@ -153,7 +153,8 @@ const AdminUserForm = ({ userData, onReload, context, refetchUserFormData, roleD await eventStats({ params: [{ eventName: 'updateCounter', settingsId: 'Manual_Entry_User_Count' }], }); - queryClient.invalidateQueries(['pendingUsersCount'], { + queryClient.invalidateQueries({ + queryKey: ['pendingUsersCount'], refetchType: 'all', }); router.navigate(`/admin/users/created/${_id}`); diff --git a/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx b/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx index 9db114a0e775..eac93149cc4f 100644 --- a/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx @@ -18,14 +18,14 @@ type AdminUserFormWithDataProps = { const AdminUserFormWithData = ({ uid, onReload, context, roleData, roleError }: AdminUserFormWithDataProps): ReactElement => { const { t } = useTranslation(); - const { data, isLoading, isError, refetch } = useUserInfoQuery({ userId: uid }); + const { data, isPending, isError, refetch } = useUserInfoQuery({ userId: uid }); const handleReload = useEffectEvent(() => { onReload(); refetch(); }); - if (isLoading) { + if (isPending) { return ( diff --git a/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx b/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx index edc928709454..3a95fe93a409 100644 --- a/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx @@ -1,7 +1,7 @@ import type { IUser } from '@rocket.chat/core-typings'; import { Callout } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import { useSetting, useRolesDescription, useTranslation, useEndpoint, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useSetting, useRolesDescription, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import { useMemo } from 'react'; @@ -31,20 +31,16 @@ const AdminUserInfoWithData = ({ uid, onReload, tab }: AdminUserInfoWithDataProp const query = useMemo(() => ({ userId: uid }), [uid]); - const dispatchToastMessage = useToastMessageDispatch(); - - const { data, isLoading, error, refetch } = useQuery( - ['users', query, 'admin'], - async () => { + const { data, isPending, error, refetch } = useQuery({ + queryKey: ['users', query, 'admin'], + queryFn: async () => { const usersInfo = await getUsersInfo(query); return usersInfo; }, - { - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); - }, + meta: { + apiErrorToastMessage: true, }, - ); + }); const onChange = useMutableCallback(() => { onReload(); @@ -97,7 +93,7 @@ const AdminUserInfoWithData = ({ uid, onReload, tab }: AdminUserInfoWithDataProp }; }, [approveManuallyUsers, data, getRoles]); - if (isLoading) { + if (isPending) { return ( diff --git a/apps/meteor/client/views/admin/users/AdminUsersPage.tsx b/apps/meteor/client/views/admin/users/AdminUsersPage.tsx index dd4cb74c109d..0a792ef75dde 100644 --- a/apps/meteor/client/views/admin/users/AdminUsersPage.tsx +++ b/apps/meteor/client/views/admin/users/AdminUsersPage.tsx @@ -59,7 +59,10 @@ const AdminUsersPage = (): ReactElement => { const isCreateUserDisabled = useShouldPreventAction('activeUsers'); const getRoles = useEndpoint('GET', '/v1/roles.list'); - const { data, error } = useQuery(['roles'], async () => getRoles()); + const { data, error } = useQuery({ + queryKey: ['roles'], + queryFn: async () => getRoles(), + }); const paginationData = usePagination(); const sortData = useSort('name'); diff --git a/apps/meteor/client/views/admin/users/hooks/useFilteredUsers.ts b/apps/meteor/client/views/admin/users/hooks/useFilteredUsers.ts index 788690e84022..857cb51826f2 100644 --- a/apps/meteor/client/views/admin/users/hooks/useFilteredUsers.ts +++ b/apps/meteor/client/views/admin/users/hooks/useFilteredUsers.ts @@ -1,5 +1,5 @@ import type { UsersListStatusParamsGET } from '@rocket.chat/rest-typings'; -import { useEndpoint, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { MutableRefObject } from 'react'; import { useMemo } from 'react'; @@ -52,10 +52,11 @@ const useFilteredUsers = ({ searchTerm, prevSearchTerm, sortData, paginationData }; }, [current, itemsPerPage, prevSearchTerm, searchTerm, selectedRoles, setCurrent, sortBy, sortDirection, tab]); const getUsers = useEndpoint('GET', '/v1/users.listByStatus'); - const dispatchToastMessage = useToastMessageDispatch(); - const usersListQueryResult = useQuery(['users.list', payload, tab], async () => getUsers(payload), { - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); + const usersListQueryResult = useQuery({ + queryKey: ['users.list', payload, tab], + queryFn: async () => getUsers(payload), + meta: { + apiErrorToastMessage: true, }, }); return usersListQueryResult; diff --git a/apps/meteor/client/views/admin/users/hooks/usePendingUsersCount.ts b/apps/meteor/client/views/admin/users/hooks/usePendingUsersCount.ts index 6729489d8b50..7010a3a50ff1 100644 --- a/apps/meteor/client/views/admin/users/hooks/usePendingUsersCount.ts +++ b/apps/meteor/client/views/admin/users/hooks/usePendingUsersCount.ts @@ -6,9 +6,10 @@ import { useQuery } from '@tanstack/react-query'; const usePendingUsersCount = (users: Serialized | undefined) => { const getUsers = useEndpoint('GET', '/v1/users.listByStatus'); - return useQuery( - ['pendingUsersCount', users], - async () => { + return useQuery({ + queryKey: ['pendingUsersCount', users], + + queryFn: async () => { const payload: UsersListStatusParamsGET = { hasLoggedIn: false, status: 'deactivated', @@ -18,8 +19,10 @@ const usePendingUsersCount = (users: Serialized | undefined) return getUsers(payload); }, - { enabled: !!users, select: (data) => data?.total }, - ); + + enabled: !!users, + select: (data) => data?.total, + }); }; export default usePendingUsersCount; diff --git a/apps/meteor/client/views/admin/users/hooks/useSendInvitationEmailMutation.ts b/apps/meteor/client/views/admin/users/hooks/useSendInvitationEmailMutation.ts index 0fe83f5c4f3f..f7563b095b4a 100644 --- a/apps/meteor/client/views/admin/users/hooks/useSendInvitationEmailMutation.ts +++ b/apps/meteor/client/views/admin/users/hooks/useSendInvitationEmailMutation.ts @@ -17,14 +17,13 @@ export const useSendInvitationEmailMutation = (): UseMutationResult< const sendInvites = useEndpoint('POST', '/v1/sendInvitationEmail'); - return useMutation( - async ({ emails }) => { + return useMutation({ + mutationFn: async ({ emails }) => { const result = await sendInvites({ emails }); return result; }, - { - onSuccess: () => dispatchToastMessage({ type: 'success', message: t('Sending_Invitations') }), - onError: (error) => dispatchToastMessage({ type: 'error', message: error }), - }, - ); + + onSuccess: () => dispatchToastMessage({ type: 'success', message: t('Sending_Invitations') }), + onError: (error) => dispatchToastMessage({ type: 'error', message: error }), + }); }; diff --git a/apps/meteor/client/views/admin/users/hooks/useSendWelcomeEmailMutation.ts b/apps/meteor/client/views/admin/users/hooks/useSendWelcomeEmailMutation.ts index 7aaf3fb26171..d4e42c2beb42 100644 --- a/apps/meteor/client/views/admin/users/hooks/useSendWelcomeEmailMutation.ts +++ b/apps/meteor/client/views/admin/users/hooks/useSendWelcomeEmailMutation.ts @@ -13,8 +13,8 @@ export const useSendWelcomeEmailMutation = (): UseMutationResult { + return useMutation({ + mutationFn: async ({ email }) => { if (!email) { dispatchToastMessage({ type: 'error', message: t('Welcome_email_failed') }); return null; @@ -22,9 +22,8 @@ export const useSendWelcomeEmailMutation = (): UseMutationResult dispatchToastMessage({ type: 'success', message: t('Welcome_email_resent') }), - onError: (error) => dispatchToastMessage({ type: 'error', message: error }), - }, - ); + + onSuccess: () => dispatchToastMessage({ type: 'success', message: t('Welcome_email_resent') }), + onError: (error) => dispatchToastMessage({ type: 'error', message: error }), + }); }; diff --git a/apps/meteor/client/views/admin/users/hooks/useSmtpQuery.ts b/apps/meteor/client/views/admin/users/hooks/useSmtpQuery.ts index 471f28727af4..22b84e647bb1 100644 --- a/apps/meteor/client/views/admin/users/hooks/useSmtpQuery.ts +++ b/apps/meteor/client/views/admin/users/hooks/useSmtpQuery.ts @@ -3,5 +3,8 @@ import { useQuery } from '@tanstack/react-query'; export const useSmtpQuery = () => { const getSmtpConfig = useEndpoint('GET', '/v1/smtp.check'); - return useQuery(['smtp.check'], async () => getSmtpConfig()); + return useQuery({ + queryKey: ['smtp.check'], + queryFn: async () => getSmtpConfig(), + }); }; diff --git a/apps/meteor/client/views/admin/users/useSeatsCap.ts b/apps/meteor/client/views/admin/users/useSeatsCap.ts index fdee7f0d32a3..683dee649687 100644 --- a/apps/meteor/client/views/admin/users/useSeatsCap.ts +++ b/apps/meteor/client/views/admin/users/useSeatsCap.ts @@ -11,7 +11,10 @@ export const useSeatsCap = (): SeatCapProps | undefined => { // #TODO: Stop using this endpoint const fetch = useEndpoint('GET', '/v1/licenses.maxActiveUsers'); - const result = useQuery(['/v1/licenses.maxActiveUsers'], () => fetch()); + const result = useQuery({ + queryKey: ['/v1/licenses.maxActiveUsers'], + queryFn: () => fetch(), + }); if (!result.isSuccess) { return undefined; diff --git a/apps/meteor/client/views/admin/users/voip/AssignExtensionModal.tsx b/apps/meteor/client/views/admin/users/voip/AssignExtensionModal.tsx index 4ea672437907..fb7c7a8e523f 100644 --- a/apps/meteor/client/views/admin/users/voip/AssignExtensionModal.tsx +++ b/apps/meteor/client/views/admin/users/voip/AssignExtensionModal.tsx @@ -46,14 +46,12 @@ const AssignExtensionModal = ({ defaultExtension, defaultUsername, onClose }: As const selectedUsername = useWatch({ control, name: 'username' }); const selectedExtension = useWatch({ control, name: 'extension' }); - const { data: availableExtensions = [], isLoading } = useQuery( - ['/v1/voip-freeswitch.extension.list', selectedUsername], - () => getAvailableExtensions({ type: 'available' as const, username: selectedUsername }), - { - select: (data) => data.extensions || [], - enabled: !!selectedUsername, - }, - ); + const { data: availableExtensions = [], isLoading } = useQuery({ + queryKey: ['/v1/voip-freeswitch.extension.list', selectedUsername], + queryFn: () => getAvailableExtensions({ type: 'available' as const, username: selectedUsername }), + select: (data) => data.extensions || [], + enabled: !!selectedUsername, + }); const extensionOptions = useMemo<[string, string][]>( () => availableExtensions.map(({ extension }) => [extension, extension]), @@ -64,9 +62,13 @@ const AssignExtensionModal = ({ defaultExtension, defaultUsername, onClose }: As mutationFn: async ({ username, extension }: FormValue) => { await assignUser({ username, extension }); - queryClient.invalidateQueries(['users.list']); + queryClient.invalidateQueries({ + queryKey: ['users.list'], + }); if (loggedUser?.username === username) { - queryClient.invalidateQueries(['voip-client']); + queryClient.invalidateQueries({ + queryKey: ['voip-client'], + }); } onClose(); diff --git a/apps/meteor/client/views/admin/users/voip/RemoveExtensionModal.tsx b/apps/meteor/client/views/admin/users/voip/RemoveExtensionModal.tsx index 180780542ef1..507b20cb9682 100644 --- a/apps/meteor/client/views/admin/users/voip/RemoveExtensionModal.tsx +++ b/apps/meteor/client/views/admin/users/voip/RemoveExtensionModal.tsx @@ -29,9 +29,13 @@ const RemoveExtensionModal = ({ name, extension, username, onClose }: RemoveExte onSuccess: () => { dispatchToastMessage({ type: 'success', message: t('Extension_removed') }); - queryClient.invalidateQueries(['users.list']); + queryClient.invalidateQueries({ + queryKey: ['users.list'], + }); if (loggedUser?.username === username) { - queryClient.invalidateQueries(['voip-client']); + queryClient.invalidateQueries({ + queryKey: ['voip-client'], + }); } onClose(); @@ -68,7 +72,7 @@ const RemoveExtensionModal = ({ name, extension, username, onClose }: RemoveExte - diff --git a/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx b/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx index c0fec91262e5..bfe5ba0a4386 100644 --- a/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx +++ b/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx @@ -46,7 +46,7 @@ const VersionCard = ({ serverInfo }: VersionCardProps): ReactElement => { const formatDate = useFormatDate(); - const { data: licenseData, isLoading, refetch: refetchLicense } = useLicense({ loadValues: true }); + const { data: licenseData, isPending, refetch: refetchLicense } = useLicense({ loadValues: true }); const { isRegistered } = useRegistrationStatus(); const { license, limits } = licenseData || {}; @@ -168,7 +168,7 @@ const VersionCard = ({ serverInfo }: VersionCardProps): ReactElement => { ).sort((a) => (a.danger ? -1 : 1)); }, [isOverLimits, t, isAirgapped, versions, versionStatus?.label, versionStatus?.expiration, formatDate, isRegistered]); - if (isLoading && !licenseData) { + if (isPending && !licenseData) { return ( diff --git a/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx b/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx index f455092be61f..d80e4e084203 100644 --- a/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx +++ b/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx @@ -22,7 +22,7 @@ const WorkspaceRoute = (): ReactElement => { return ; } - if (serverInfoQuery.isLoading || instancesQuery.isLoading || statisticsQuery.isLoading) { + if (serverInfoQuery.isPending || instancesQuery.isPending || statisticsQuery.isPending) { return ; } @@ -40,7 +40,7 @@ const WorkspaceRoute = (): ReactElement => { - @@ -57,7 +57,7 @@ const WorkspaceRoute = (): ReactElement => { canViewStatistics={canViewStatistics} serverInfo={serverInfoQuery.data} statistics={statisticsQuery.data} - statisticsIsLoading={statisticsQuery.isLoading} + statisticsIsLoading={statisticsQuery.isPending} instances={instancesQuery.data} onClickRefreshButton={handleClickRefreshButton} onClickDownloadInfo={handleClickDownloadInfo} diff --git a/apps/meteor/client/views/audit/AuditPage.tsx b/apps/meteor/client/views/audit/AuditPage.tsx index 78e5649520e0..a7e793d9a036 100644 --- a/apps/meteor/client/views/audit/AuditPage.tsx +++ b/apps/meteor/client/views/audit/AuditPage.tsx @@ -43,7 +43,7 @@ const AuditPage = () => { {t('Encrypted_content_cannot_be_searched_and_audited_subtitle')} ) : null} - {auditMutation.isLoading && } + {auditMutation.isPending && } {auditMutation.isError && ( diff --git a/apps/meteor/client/views/audit/components/AuditLogTable.tsx b/apps/meteor/client/views/audit/components/AuditLogTable.tsx index 16a660b23945..06b61963ec6d 100644 --- a/apps/meteor/client/views/audit/components/AuditLogTable.tsx +++ b/apps/meteor/client/views/audit/components/AuditLogTable.tsx @@ -1,5 +1,5 @@ import { Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage'; -import { useTranslation, useMethod, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useTranslation, useMethod } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import { useState } from 'react'; @@ -25,22 +25,19 @@ const AuditLogTable = (): ReactElement => { end: createEndOfToday(), })); - const dispatchToastMessage = useToastMessageDispatch(); - const getAudits = useMethod('auditGetAuditions'); - const { data, isLoading, isSuccess } = useQuery( - ['audits', dateRange], - async () => { + const { data, isLoading, isSuccess } = useQuery({ + queryKey: ['audits', dateRange], + + queryFn: async () => { const { start, end } = dateRange; return getAudits({ startDate: start ?? new Date(0), endDate: end ?? new Date() }); }, - { - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); - }, + meta: { + apiErrorToastMessage: true, }, - ); + }); const headers = ( <> diff --git a/apps/meteor/client/views/audit/components/forms/VisitorAutoComplete.tsx b/apps/meteor/client/views/audit/components/forms/VisitorAutoComplete.tsx index d9631655d78f..c5b3dd71927d 100644 --- a/apps/meteor/client/views/audit/components/forms/VisitorAutoComplete.tsx +++ b/apps/meteor/client/views/audit/components/forms/VisitorAutoComplete.tsx @@ -11,9 +11,11 @@ const VisitorAutoComplete = ({ value, onChange, ...props }: VisitorAutoCompleteP const performVisitorSearch = useEndpoint('GET', '/v1/livechat/visitors.autocomplete'); - const visitorAutocompleteQueryResult = useQuery(['audit', 'visitors', filter], () => - performVisitorSearch({ selector: JSON.stringify({ term: filter ?? '' }) }), - ); + const visitorAutocompleteQueryResult = useQuery({ + queryKey: ['audit', 'visitors', filter], + + queryFn: () => performVisitorSearch({ selector: JSON.stringify({ term: filter ?? '' }) }), + }); const options = useMemo( () => visitorAutocompleteQueryResult.data?.items.map((user) => ({ value: user._id, label: user.name ?? user.username })) ?? [], diff --git a/apps/meteor/client/views/audit/hooks/useAuditMutation.ts b/apps/meteor/client/views/audit/hooks/useAuditMutation.ts index 683364784553..68f7a27abf02 100644 --- a/apps/meteor/client/views/audit/hooks/useAuditMutation.ts +++ b/apps/meteor/client/views/audit/hooks/useAuditMutation.ts @@ -8,28 +8,32 @@ export const useAuditMutation = (type: IAuditLog['fields']['type']) => { const getAuditMessages = useMethod('auditGetMessages'); const getOmnichannelAuditMessages = useMethod('auditGetOmnichannelMessages'); - return useMutation(['audit'] as const, async ({ msg, dateRange, rid, users, visitor, agent }: AuditFields) => { - if (type === 'l') { - return getOmnichannelAuditMessages({ + return useMutation({ + mutationKey: ['audit'] as const, + + mutationFn: async ({ msg, dateRange, rid, users, visitor, agent }: AuditFields) => { + if (type === 'l') { + return getOmnichannelAuditMessages({ + type, + msg, + startDate: dateRange.start ?? new Date(0), + endDate: dateRange.end ?? new Date(), + users, + visitor: '', + agent: '', + }); + } + + return getAuditMessages({ type, msg, startDate: dateRange.start ?? new Date(0), endDate: dateRange.end ?? new Date(), + rid, users, - visitor: '', - agent: '', + visitor, + agent, }); - } - - return getAuditMessages({ - type, - msg, - startDate: dateRange.start ?? new Date(0), - endDate: dateRange.end ?? new Date(), - rid, - users, - visitor, - agent, - }); + }, }); }; diff --git a/apps/meteor/client/views/audit/hooks/useSendTelemetryMutation.ts b/apps/meteor/client/views/audit/hooks/useSendTelemetryMutation.ts index ee427a4d3c30..fc66d0df93d3 100644 --- a/apps/meteor/client/views/audit/hooks/useSendTelemetryMutation.ts +++ b/apps/meteor/client/views/audit/hooks/useSendTelemetryMutation.ts @@ -4,7 +4,8 @@ import { useMutation } from '@tanstack/react-query'; export const useSendTelemetryMutation = () => { const sendTelemetry = useEndpoint('POST', '/v1/statistics.telemetry'); - return useMutation(sendTelemetry, { + return useMutation({ + mutationFn: sendTelemetry, onError: (error) => { console.warn(error); }, diff --git a/apps/meteor/client/views/banners/hooks/useDismissUserBannerMutation.ts b/apps/meteor/client/views/banners/hooks/useDismissUserBannerMutation.ts index 7b15c148539b..5a881d4b5ec5 100644 --- a/apps/meteor/client/views/banners/hooks/useDismissUserBannerMutation.ts +++ b/apps/meteor/client/views/banners/hooks/useDismissUserBannerMutation.ts @@ -6,7 +6,8 @@ export const useDismissUserBannerMutation = () => { const dispatchToastMessage = useToastMessageDispatch(); - return useMutation(dismissBanner, { + return useMutation({ + mutationFn: dismissBanner, onError: (error) => { dispatchToastMessage({ type: 'error', message: error }); }, diff --git a/apps/meteor/client/views/cloud/CloudAnnouncementsRegion.tsx b/apps/meteor/client/views/cloud/CloudAnnouncementsRegion.tsx index 9445e6a03d2a..1ece6fa2371d 100644 --- a/apps/meteor/client/views/cloud/CloudAnnouncementsRegion.tsx +++ b/apps/meteor/client/views/cloud/CloudAnnouncementsRegion.tsx @@ -29,11 +29,15 @@ const CloudAnnouncementsRegion = () => { } const unsubscribeFromBannerChanged = subscribeToNotifyLoggedIn('banner-changed', async () => { - queryClient.invalidateQueries(['cloud', 'announcements']); + queryClient.invalidateQueries({ + queryKey: ['cloud', 'announcements'], + }); }); const unsubscribeBanners = subscribeToNotifyUser(`${uid}/banners`, async () => { - queryClient.invalidateQueries(['cloud', 'announcements']); + queryClient.invalidateQueries({ + queryKey: ['cloud', 'announcements'], + }); }); return () => { diff --git a/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx b/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx index d42c7baaa2c7..91a55952bca3 100644 --- a/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx +++ b/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx @@ -82,7 +82,10 @@ const ChannelsTable = () => { const getDirectoryData = useEndpoint('GET', '/v1/directory'); const query = useDirectoryQuery({ text, current, itemsPerPage }, [sortBy, sortDirection], 'channels'); - const { data, isFetched, isLoading, isError, refetch } = useQuery(['getDirectoryData', query], () => getDirectoryData(query)); + const { data, isFetched, isLoading, isError, refetch } = useQuery({ + queryKey: ['getDirectoryData', query], + queryFn: () => getDirectoryData(query), + }); const onClick = useMemo( () => (name: IRoom['name'], type: IRoom['t']) => (e: KeyboardEvent | MouseEvent) => { diff --git a/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx b/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx index b96a2a2bc897..e4788d9e5b3e 100644 --- a/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx +++ b/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx @@ -58,7 +58,10 @@ const TeamsTable = () => { const getDirectoryData = useEndpoint('GET', '/v1/directory'); const query = useDirectoryQuery({ text, current, itemsPerPage }, [sortBy, sortDirection], 'teams'); - const { data, isFetched, isLoading, isError, refetch } = useQuery(['getDirectoryData', query], () => getDirectoryData(query)); + const { data, isFetched, isLoading, isError, refetch } = useQuery({ + queryKey: ['getDirectoryData', query], + queryFn: () => getDirectoryData(query), + }); const onClick = useMemo( () => (name: IRoom['name'], type: IRoom['t']) => (e: KeyboardEvent | MouseEvent) => { diff --git a/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx b/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx index 9668952fb1a7..01adb7a9cd00 100644 --- a/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx +++ b/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx @@ -81,7 +81,10 @@ const UsersTable = ({ workspace = 'local' }): ReactElement => { const query = useDirectoryQuery({ text, current, itemsPerPage }, [sortBy, sortDirection], 'users', workspace); const getDirectoryData = useEndpoint('GET', '/v1/directory'); - const { data, isFetched, isLoading, isError, refetch } = useQuery(['getDirectoryData', query], () => getDirectoryData(query)); + const { data, isFetched, isLoading, isError, refetch } = useQuery({ + queryKey: ['getDirectoryData', query], + queryFn: () => getDirectoryData(query), + }); const handleClick = useCallback( (username: IUser['username']) => (e: KeyboardEvent | MouseEvent) => { diff --git a/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx b/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx index 2d56bff7fb6c..ee7ba85713bc 100644 --- a/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx +++ b/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx @@ -2,7 +2,7 @@ import type { IRoom, RoomAdminFieldsType } from '@rocket.chat/core-typings'; import { isRoomFederated } from '@rocket.chat/core-typings'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useSetModal, useToastMessageDispatch, useRouter, usePermission, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useMutation, useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useMutation, useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import GenericModal from '../../../components/GenericModal'; @@ -22,8 +22,10 @@ export const useDeleteRoom = (room: IRoom | Pick, { const teamsInfoEndpoint = useEndpoint('GET', '/v1/teams.info'); const teamId = room.teamId || ''; - const { data: teamInfoData } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { - keepPreviousData: true, + const { data: teamInfoData } = useQuery({ + queryKey: ['teamId', teamId], + queryFn: async () => teamsInfoEndpoint({ teamId }), + placeholderData: keepPreviousData, retry: false, enabled: room.teamId !== '', }); @@ -71,7 +73,7 @@ export const useDeleteRoom = (room: IRoom | Pick, { }, }); - const isDeleting = deleteTeamMutation.isLoading || deleteRoomMutation.isLoading; + const isDeleting = deleteTeamMutation.isPending || deleteRoomMutation.isPending; const handleDelete = useMutableCallback(() => { const handleDeleteTeam = async (roomsToRemove: IRoom['_id'][]) => { diff --git a/apps/meteor/client/views/hooks/useActiveConnections.ts b/apps/meteor/client/views/hooks/useActiveConnections.ts index 3bb3299e17c9..f52403f7d8f7 100644 --- a/apps/meteor/client/views/hooks/useActiveConnections.ts +++ b/apps/meteor/client/views/hooks/useActiveConnections.ts @@ -4,12 +4,14 @@ import { useQuery } from '@tanstack/react-query'; export const useActiveConnections = (): UseQueryResult<{ max: number; current: number; percentage: number }> => { const getConnections = useEndpoint('GET', '/v1/presence.getConnections'); - return useQuery( - ['userConnections'], - async () => { + return useQuery({ + queryKey: ['userConnections'], + + queryFn: async () => { const { current, max } = await getConnections(); return { current, max, percentage: Math.min((current / max) * 100, 100) }; }, - { staleTime: 1000 * 60 }, - ); + + staleTime: 1000 * 60, + }); }; diff --git a/apps/meteor/client/views/hooks/useMemberExists.ts b/apps/meteor/client/views/hooks/useMemberExists.ts index f737ea6c4e94..f52ca3a2ee72 100644 --- a/apps/meteor/client/views/hooks/useMemberExists.ts +++ b/apps/meteor/client/views/hooks/useMemberExists.ts @@ -6,5 +6,8 @@ type UseMemberExistsProps = { roomId: string; username: string }; export const useMemberExists = ({ roomId, username }: UseMemberExistsProps) => { const checkMember = useEndpoint('GET', '/v1/rooms.isMember'); - return useQuery(['rooms/isMember', roomId, username], () => checkMember({ roomId, username })); + return useQuery({ + queryKey: ['rooms/isMember', roomId, username], + queryFn: () => checkMember({ roomId, username }), + }); }; diff --git a/apps/meteor/client/views/hooks/useMembersList.ts b/apps/meteor/client/views/hooks/useMembersList.ts index 1dc79775908a..84c95c2d373b 100644 --- a/apps/meteor/client/views/hooks/useMembersList.ts +++ b/apps/meteor/client/views/hooks/useMembersList.ts @@ -18,9 +18,9 @@ const endpointsByRoomType = { export const useMembersList = (options: MembersListOptions) => { const getMembers = useEndpoint('GET', endpointsByRoomType[options.roomType]); - return useInfiniteQuery( - [options.roomType, 'members', options.rid, options.type, options.debouncedText], - async ({ pageParam }) => { + return useInfiniteQuery({ + queryKey: [options.roomType, 'members', options.rid, options.type, options.debouncedText], + queryFn: async ({ pageParam }) => { const start = pageParam ?? 0; return getMembers({ @@ -31,12 +31,11 @@ export const useMembersList = (options: MembersListOptions) => { ...(options.type !== 'all' && { status: [options.type] }), }); }, - { - getNextPageParam: (lastPage) => { - const offset = lastPage.offset + lastPage.count; - // if the offset is greater than the total, return undefined to stop the query from trying to fetch another page - return offset >= lastPage.total ? undefined : offset; - }, + getNextPageParam: (lastPage) => { + const offset = lastPage.offset + lastPage.count; + // if the offset is greater than the total, return undefined to stop the query from trying to fetch another page + return offset >= lastPage.total ? undefined : offset; }, - ); + initialPageParam: 0, + }); }; diff --git a/apps/meteor/client/views/hooks/useStatistics.ts b/apps/meteor/client/views/hooks/useStatistics.ts index 9b1a589253da..69f358e9f3c1 100644 --- a/apps/meteor/client/views/hooks/useStatistics.ts +++ b/apps/meteor/client/views/hooks/useStatistics.ts @@ -8,5 +8,9 @@ type UseStatisticsOptions = { export const useStatistics = ({ refresh }: UseStatisticsOptions = { refresh: 'false' }) => { const getStatistics = useEndpoint('GET', '/v1/statistics'); - return useQuery(['analytics'], () => getStatistics({ refresh }), { staleTime: 10 * 60 * 1000 }); + return useQuery({ + queryKey: ['analytics'], + queryFn: () => getStatistics({ refresh }), + staleTime: 10 * 60 * 1000, + }); }; diff --git a/apps/meteor/client/views/invite/InvitePage.tsx b/apps/meteor/client/views/invite/InvitePage.tsx index fcd69e4c0a6d..a969bf783e5e 100644 --- a/apps/meteor/client/views/invite/InvitePage.tsx +++ b/apps/meteor/client/views/invite/InvitePage.tsx @@ -14,7 +14,7 @@ const InvitePage = (): ReactElement => { const token = useRouteParameter('hash'); const userId = useUserId(); - const { isLoading, data: isValidInvite } = useValidateInviteQuery(userId, token); + const { isPending, data: isValidInvite } = useValidateInviteQuery(userId, token); const getInviteRoomMutation = useInviteTokenMutation(); @@ -24,7 +24,7 @@ const InvitePage = (): ReactElement => { } }, [getInviteRoomMutation, token, userId]); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/invite/hooks/useValidateInviteQuery.ts b/apps/meteor/client/views/invite/hooks/useValidateInviteQuery.ts index 106a8c14c6b2..869f707f1cf3 100644 --- a/apps/meteor/client/views/invite/hooks/useValidateInviteQuery.ts +++ b/apps/meteor/client/views/invite/hooks/useValidateInviteQuery.ts @@ -15,9 +15,9 @@ export const useValidateInviteQuery = (userId: string | null, token: string | un const handleValidateInviteToken = useEndpoint('POST', '/v1/validateInviteToken'); - return useQuery( - ['invite', token], - async () => { + const result = useQuery({ + queryKey: ['invite', token], + queryFn: async () => { if (!token) { return false; } @@ -25,30 +25,33 @@ export const useValidateInviteQuery = (userId: string | null, token: string | un try { const { valid } = await handleValidateInviteToken({ token }); + // FIXME: decouple this state management from the query + const onSuccess = async () => { + if (!token) { + return; + } + + if (registrationForm !== 'Disabled') { + setLoginDefaultState('invite-register'); + } else { + setLoginDefaultState('login'); + } + + if (!valid || !userId) { + return; + } + + return getInviteRoomMutation(token); + }; + + onSuccess(); return valid; } catch (error) { dispatchToastMessage({ type: 'error', message: t('Failed_to_validate_invite_token') }); return false; } }, - { - onSuccess: async (valid) => { - if (!token) { - return; - } - - if (registrationForm !== 'Disabled') { - setLoginDefaultState('invite-register'); - } else { - setLoginDefaultState('login'); - } - - if (!valid || !userId) { - return; - } - - return getInviteRoomMutation(token); - }, - }, - ); + }); + + return result; }; diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx index fba2d2065589..9ddbf5a7237f 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx @@ -1,6 +1,6 @@ import type { App } from '@rocket.chat/core-typings'; import { Accordion } from '@rocket.chat/fuselage'; -import { useEndpoint, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import { useTranslation } from 'react-i18next'; @@ -10,12 +10,11 @@ import AccordionLoading from '../../../components/AccordionLoading'; const AppReleases = ({ id }: { id: App['id'] }): ReactElement => { const getVersions = useEndpoint('GET', '/apps/:id/versions', { id }); - const dispatchToastMessage = useToastMessageDispatch(); const { t } = useTranslation(); - const { data, isLoading, isFetched } = useQuery( - ['apps', id, 'versions'], - async () => { + const { data, isLoading, isFetched } = useQuery({ + queryKey: ['apps', id, 'versions'], + queryFn: async () => { const { apps } = await getVersions(); if (apps.length === 0) { @@ -23,12 +22,10 @@ const AppReleases = ({ id }: { id: App['id'] }): ReactElement => { } return apps; }, - { - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); - }, + meta: { + apiErrorToastMessage: true, }, - ); + }); return ( <> diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx index fb9176653fc3..7e09517f9c30 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx @@ -1,7 +1,7 @@ import type { App } from '@rocket.chat/core-typings'; import { Box, Pagination, States, StatesSubtitle, StatesTitle } from '@rocket.chat/fuselage'; import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useMutation } from '@tanstack/react-query'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; import type { ReactElement, SetStateAction } from 'react'; import { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; @@ -9,7 +9,6 @@ import { useTranslation } from 'react-i18next'; import AppRequestItem from './AppRequestItem'; import AppRequestsLoading from './AppRequestsLoading'; import { useAppsReload } from '../../../../../contexts/hooks/useAppsReload'; -import { queryClient } from '../../../../../lib/queryClient'; import { useAppRequests } from '../../../hooks/useAppRequests'; type itemsPerPage = 25 | 50 | 100; @@ -31,6 +30,9 @@ const AppRequests = ({ id, isAdminUser }: { id: App['id']; isAdminUser: boolean mutationFn: (unseenRequests: Array) => markSeen({ unseenRequests }), retry: false, }); + + const queryClient = useQueryClient(); + useEffect(() => { return () => { if (isAdminUser && paginatedAppRequests.isSuccess) { diff --git a/apps/meteor/client/views/marketplace/components/MarketplaceRequestBadge.tsx b/apps/meteor/client/views/marketplace/components/MarketplaceRequestBadge.tsx index b1fdbbb78a48..a38c541e6378 100644 --- a/apps/meteor/client/views/marketplace/components/MarketplaceRequestBadge.tsx +++ b/apps/meteor/client/views/marketplace/components/MarketplaceRequestBadge.tsx @@ -5,7 +5,7 @@ import { useAppRequestStats } from '../hooks/useAppRequestStats'; const MarketplaceRequestBadge = () => { const requestStatsResult = useAppRequestStats(); - if (requestStatsResult.isLoading) + if (requestStatsResult.isPending) return requestStatsResult.fetchStatus !== 'idle' ? : null; if (requestStatsResult.isError) return null; diff --git a/apps/meteor/client/views/marketplace/hooks/useAppRequests.ts b/apps/meteor/client/views/marketplace/hooks/useAppRequests.ts index 885e65ed22fb..b566b4fa16d4 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppRequests.ts +++ b/apps/meteor/client/views/marketplace/hooks/useAppRequests.ts @@ -8,6 +8,6 @@ export const useAppRequests = (appId: string, limit?: number, offset?: number, s return useQuery({ queryKey: ['app-requests', appId, limit, offset], queryFn: async () => fetchAppRequests({ appId, q: filter, sort, limit, offset }), - cacheTime: 0, + gcTime: 0, }); }; diff --git a/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts b/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts index 712bcf9da941..8a7c3e3e33da 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts +++ b/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts @@ -11,9 +11,10 @@ export function isMarketplaceRouteContext(context: string): context is Marketpla export const useAppsCountQuery = (context: MarketplaceRouteContext) => { const getAppsCount = useEndpoint('GET', '/apps/count'); - return useQuery( - ['apps/count', context], - async () => { + return useQuery({ + queryKey: ['apps/count', context], + + queryFn: async () => { const data = await getAppsCount(); const numberOfEnabledApps = context === 'private' ? data.totalPrivateEnabled : data.totalMarketplaceEnabled; @@ -27,13 +28,16 @@ export const useAppsCountQuery = (context: MarketplaceRouteContext) => { // tooltip, }; }, - { staleTime: 10_000 }, - ); + + staleTime: 10_000, + }); }; export const useInvalidateAppsCountQueryCallback = () => { const queryClient = useQueryClient(); return useCallback(() => { - queryClient.invalidateQueries(['apps/count']); + queryClient.invalidateQueries({ + queryKey: ['apps/count'], + }); }, [queryClient]); }; diff --git a/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx b/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx index 90a4f7dbbfa7..be0ca31dc426 100644 --- a/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx @@ -28,9 +28,10 @@ export const useInstallApp = (file: File): { install: () => void; isInstalling: const [isInstalling, setInstalling] = useState(false); - const { mutate: sendFile } = useMutation( - ['apps/installPrivateApp'], - ({ permissionsGranted, appFile, appId }: { permissionsGranted: AppPermission[]; appFile: File; appId?: string }) => { + const { mutate: sendFile } = useMutation({ + mutationKey: ['apps/installPrivateApp'], + + mutationFn: ({ permissionsGranted, appFile, appId }: { permissionsGranted: AppPermission[]; appFile: File; appId?: string }) => { const fileData = new FormData(); fileData.append('app', appFile, appFile.name); fileData.append('permissions', JSON.stringify(permissionsGranted)); @@ -41,27 +42,28 @@ export const useInstallApp = (file: File): { install: () => void; isInstalling: return uploadAppEndpoint(fileData) as any; }, - { - onSuccess: (data: { app: App }) => { - router.navigate({ - name: 'marketplace', - params: { - context: 'private', - page: 'info', - id: data.app.id, - }, - }); - }, - onError: (e) => { - handleAPIError(e); - }, - onSettled: () => { - setInstalling(false); - setModal(null); - reloadAppsList(); - }, + + onSuccess: (data: { app: App }) => { + router.navigate({ + name: 'marketplace', + params: { + context: 'private', + page: 'info', + id: data.app.id, + }, + }); + }, + + onError: (e) => { + handleAPIError(e); + }, + + onSettled: () => { + setInstalling(false); + setModal(null); + reloadAppsList(); }, - ); + }); const cancelAction = useCallback(() => { setInstalling(false); diff --git a/apps/meteor/client/views/marketplace/hooks/useLogs.ts b/apps/meteor/client/views/marketplace/hooks/useLogs.ts index 6d117f3bf7ec..d8714e1345fa 100644 --- a/apps/meteor/client/views/marketplace/hooks/useLogs.ts +++ b/apps/meteor/client/views/marketplace/hooks/useLogs.ts @@ -6,5 +6,8 @@ import { useQuery } from '@tanstack/react-query'; export const useLogs = (appId: string): UseQueryResult> => { const logs = useEndpoint('GET', '/apps/:id/logs', { id: appId }); - return useQuery(['marketplace', 'apps', appId, 'logs'], () => logs()); + return useQuery({ + queryKey: ['marketplace', 'apps', appId, 'logs'], + queryFn: () => logs(), + }); }; diff --git a/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts b/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts index efc614a90d93..aae0964892a4 100644 --- a/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts +++ b/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts @@ -21,33 +21,33 @@ export const useMarketplaceActions = () => { throw new Error('Apps orchestrator is not available'); } - const installAppMutation = useMutation( - ({ id, marketplaceVersion, permissionsGranted }: InstallAppParams) => + const installAppMutation = useMutation({ + mutationFn: ({ id, marketplaceVersion, permissionsGranted }: InstallAppParams) => appsOrchestrator.installApp(id, marketplaceVersion, permissionsGranted), - { - onSuccess: ({ status }, { name }) => { - if (!status) return; - warnAppInstall(name, status); - }, - onError: (error) => { - handleAPIError(error); - }, + + onSuccess: ({ status }, { name }) => { + if (!status) return; + warnAppInstall(name, status); + }, + + onError: (error) => { + handleAPIError(error); }, - ); + }); - const updateAppMutation = useMutation( - ({ id, marketplaceVersion, permissionsGranted }: UpdateAppParams) => + const updateAppMutation = useMutation({ + mutationFn: ({ id, marketplaceVersion, permissionsGranted }: UpdateAppParams) => appsOrchestrator.updateApp(id, marketplaceVersion, permissionsGranted), - { - onSuccess: ({ status }, { name }) => { - if (!status) return; - warnStatusChange(name, status); - }, - onError: (error) => { - handleAPIError(error); - }, + + onSuccess: ({ status }, { name }) => { + if (!status) return; + warnStatusChange(name, status); + }, + + onError: (error) => { + handleAPIError(error); }, - ); + }); return { purchase: installAppMutation.mutateAsync, diff --git a/apps/meteor/client/views/meet/MeetRoute.tsx b/apps/meteor/client/views/meet/MeetRoute.tsx index 34055094db57..f0bcb9c43d1b 100644 --- a/apps/meteor/client/views/meet/MeetRoute.tsx +++ b/apps/meteor/client/views/meet/MeetRoute.tsx @@ -1,5 +1,6 @@ import { useEndpoint, useRouter, useSearchParameter, useToastMessageDispatch, useUserId } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import MeetPage from './MeetPage'; @@ -15,9 +16,10 @@ const MeetRoute = () => { const token = useSearchParameter('token') ?? ''; const getVisitorByToken = useEndpoint('GET', '/v1/livechat/visitor/:token', { token }); - const { data: hasVisitor } = useQuery( - ['meet', { token }], - async () => { + const { data: hasVisitor, error } = useQuery({ + queryKey: ['meet', { token }], + + queryFn: async () => { if (token) { const result = await getVisitorByToken(); if ('visitor' in result) { @@ -33,24 +35,22 @@ const MeetRoute = () => { return true; }, - { - onSuccess: (hasVisitor) => { - if (hasVisitor === false) { - router.navigate('/home'); - } - }, - onError: (error) => { - if (error instanceof VisitorDoesNotExistError) { - dispatchToastMessage({ type: 'error', message: t('core.Visitor_does_not_exist') }); - router.navigate('/home'); - return; - } + }); - dispatchToastMessage({ type: 'error', message: error }); - router.navigate('/home'); - }, - }, - ); + useEffect(() => { + if (error) { + if (error instanceof VisitorDoesNotExistError) { + dispatchToastMessage({ type: 'error', message: t('core.Visitor_does_not_exist') }); + return; + } + + dispatchToastMessage({ type: 'error', message: error }); + } + + if (!hasVisitor) { + router.navigate('/home'); + } + }, [hasVisitor, error, router, dispatchToastMessage, t]); if (!hasVisitor) { return ; diff --git a/apps/meteor/client/views/oauth/OAuthAuthorizationPage.tsx b/apps/meteor/client/views/oauth/OAuthAuthorizationPage.tsx index 09c1d2b90ffa..1d1745377c70 100644 --- a/apps/meteor/client/views/oauth/OAuthAuthorizationPage.tsx +++ b/apps/meteor/client/views/oauth/OAuthAuthorizationPage.tsx @@ -20,7 +20,7 @@ const OAuthAuthorizationPage = () => { return ; } - if (oauthAppQuery.isLoading) { + if (oauthAppQuery.isPending) { return ; } diff --git a/apps/meteor/client/views/oauth/hooks/useOAuthAppQuery.ts b/apps/meteor/client/views/oauth/hooks/useOAuthAppQuery.ts index dc0586aa0971..04fb318209aa 100644 --- a/apps/meteor/client/views/oauth/hooks/useOAuthAppQuery.ts +++ b/apps/meteor/client/views/oauth/hooks/useOAuthAppQuery.ts @@ -11,9 +11,10 @@ type UseOAuthAppQueryOptions = Omit< export const useOAuthAppQuery = (clientId: string | undefined, options?: UseOAuthAppQueryOptions) => { const getOAuthApp = useEndpoint('GET', '/v1/oauth-apps.get'); - return useQuery( - ['oauth-app', { clientId }] as const, - async () => { + return useQuery({ + queryKey: ['oauth-app', { clientId }] as const, + + queryFn: async () => { if (!clientId) { throw new Error('Invalid OAuth client'); } @@ -25,6 +26,6 @@ export const useOAuthAppQuery = (clientId: string | undefined, options?: UseOAut _updatedAt: new Date(oauthApp._updatedAt), }; }, - options, - ); + ...options, + }); }; diff --git a/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx b/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx index 974018af2e7a..17cd925c7dca 100644 --- a/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx +++ b/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx @@ -13,11 +13,15 @@ function ExternalFrameContainer() { const keyStr = useSetting('Omnichannel_External_Frame_Encryption_JWK', ''); const frameURLSetting = useSetting('Omnichannel_External_Frame_URL', ''); - const token = useQuery(['externalFrame', keyStr, authToken], async () => { - if (!keyStr || !authToken) { - return ''; - } - return encrypt(authToken, await getKeyFromString(keyStr)); + const token = useQuery({ + queryKey: ['externalFrame', keyStr, authToken], + + queryFn: async () => { + if (!keyStr || !authToken) { + return ''; + } + return encrypt(authToken, await getKeyFromString(keyStr)); + }, }); const externalFrameUrl = useMemo(() => { diff --git a/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx b/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx index 195cc2e11ded..f02d67f3b850 100644 --- a/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx +++ b/apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx @@ -109,7 +109,9 @@ const AgentEdit = ({ agentData, userDepartments, availableDepartments }: AgentEd await saveAgentInfo(agentData._id, data, departments); dispatchToastMessage({ type: 'success', message: t('Success') }); router.navigate('/omnichannel/agents'); - queryClient.invalidateQueries(['livechat-agents']); + queryClient.invalidateQueries({ + queryKey: ['livechat-agents'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } diff --git a/apps/meteor/client/views/omnichannel/agents/AgentEditWithData.tsx b/apps/meteor/client/views/omnichannel/agents/AgentEditWithData.tsx index 35f03b43ffef..259166e2627c 100644 --- a/apps/meteor/client/views/omnichannel/agents/AgentEditWithData.tsx +++ b/apps/meteor/client/views/omnichannel/agents/AgentEditWithData.tsx @@ -15,21 +15,32 @@ const AgentEditWithData = ({ uid }: { uid: ILivechatAgent['_id'] }): ReactElemen const getAgentById = useEndpoint('GET', '/v1/livechat/users/agent/:_id', { _id: uid }); const getAgentDepartments = useEndpoint('GET', '/v1/livechat/agents/:agentId/departments', { agentId: uid }); - const { data, isLoading, error } = useQuery(['livechat-getAgentById', uid], async () => getAgentById(), { refetchOnWindowFocus: false }); + const { data, isPending, error } = useQuery({ + queryKey: ['livechat-getAgentById', uid], + queryFn: async () => getAgentById(), + refetchOnWindowFocus: false, + }); const { data: agentDepartments, - isLoading: agentDepartmentsLoading, + isPending: agentDepartmentsLoading, error: agentsDepartmentsError, - } = useQuery(['livechat-getAgentDepartments', uid], async () => getAgentDepartments(), { refetchOnWindowFocus: false }); + } = useQuery({ + queryKey: ['livechat-getAgentDepartments', uid], + queryFn: async () => getAgentDepartments(), + refetchOnWindowFocus: false, + }); const { data: availableDepartments, - isLoading: availableDepartmentsLoading, + isPending: availableDepartmentsLoading, error: availableDepartmentsError, - } = useQuery(['livechat-getAvailableDepartments'], async () => getAvailableDepartments({ showArchived: 'true' })); + } = useQuery({ + queryKey: ['livechat-getAvailableDepartments'], + queryFn: async () => getAvailableDepartments({ showArchived: 'true' }), + }); - if (isLoading || availableDepartmentsLoading || agentDepartmentsLoading || !agentDepartments || !availableDepartments) { + if (isPending || availableDepartmentsLoading || agentDepartmentsLoading || !agentDepartments || !availableDepartments) { return ; } diff --git a/apps/meteor/client/views/omnichannel/agents/AgentInfo.tsx b/apps/meteor/client/views/omnichannel/agents/AgentInfo.tsx index eef0dcbd6a7f..6c23d74a56f3 100644 --- a/apps/meteor/client/views/omnichannel/agents/AgentInfo.tsx +++ b/apps/meteor/client/views/omnichannel/agents/AgentInfo.tsx @@ -26,13 +26,15 @@ const AgentInfo = ({ uid }: AgentInfoProps) => { const { t } = useTranslation(); const router = useRouter(); const getAgentById = useEndpoint('GET', '/v1/livechat/users/agent/:_id', { _id: uid }); - const { data, isLoading, isError } = useQuery(['livechat-getAgentInfoById', uid], async () => getAgentById(), { + const { data, isPending, isError } = useQuery({ + queryKey: ['livechat-getAgentInfoById', uid], + queryFn: async () => getAgentById(), refetchOnWindowFocus: false, }); const handleDelete = useRemoveAgent(uid); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/omnichannel/agents/AgentsTable/AgentsTable.tsx b/apps/meteor/client/views/omnichannel/agents/AgentsTable/AgentsTable.tsx index f266f704cc7f..ccae1aff414c 100644 --- a/apps/meteor/client/views/omnichannel/agents/AgentsTable/AgentsTable.tsx +++ b/apps/meteor/client/views/omnichannel/agents/AgentsTable/AgentsTable.tsx @@ -1,6 +1,6 @@ import { Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMediaQuery, useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import { hashQueryKey } from '@tanstack/react-query'; +import { hashKey } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -36,8 +36,8 @@ const AgentsTable = () => { const query = useQuery({ text, current, itemsPerPage }, debouncedSort); const { data, isSuccess, isLoading, refetch } = useAgentsQuery(query); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const onHeaderClick = useMutableCallback((id) => { if (sortBy === id) { diff --git a/apps/meteor/client/views/omnichannel/agents/hooks/useAgentsQuery.ts b/apps/meteor/client/views/omnichannel/agents/hooks/useAgentsQuery.ts index 8fcaba13b62d..3945126bcc3f 100644 --- a/apps/meteor/client/views/omnichannel/agents/hooks/useAgentsQuery.ts +++ b/apps/meteor/client/views/omnichannel/agents/hooks/useAgentsQuery.ts @@ -5,5 +5,8 @@ import { useQuery } from '@tanstack/react-query'; export const useAgentsQuery = (query?: PaginatedRequest) => { const getAgents = useEndpoint('GET', '/v1/livechat/users/agent'); - return useQuery(['livechat-agents', query], async () => getAgents(query || {})); + return useQuery({ + queryKey: ['livechat-agents', query], + queryFn: async () => getAgents(query || {}), + }); }; diff --git a/apps/meteor/client/views/omnichannel/agents/hooks/useRemoveAgent.tsx b/apps/meteor/client/views/omnichannel/agents/hooks/useRemoveAgent.tsx index d91770dbfb50..3970d45d6bbf 100644 --- a/apps/meteor/client/views/omnichannel/agents/hooks/useRemoveAgent.tsx +++ b/apps/meteor/client/views/omnichannel/agents/hooks/useRemoveAgent.tsx @@ -20,7 +20,9 @@ export const useRemoveAgent = (uid: ILivechatAgent['_id']) => { await deleteAction(); dispatchToastMessage({ type: 'success', message: t('Agent_removed') }); router.navigate('/omnichannel/agents'); - queryClient.invalidateQueries(['livechat-agents']); + queryClient.invalidateQueries({ + queryKey: ['livechat-agents'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } finally { diff --git a/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursWithData.tsx b/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursWithData.tsx index e0fad9a0782f..dbf1a71a1ae9 100644 --- a/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursWithData.tsx +++ b/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursWithData.tsx @@ -13,15 +13,13 @@ const EditBusinessHoursWidthData = ({ id, type }: { id?: ILivechatBusinessHour[' const router = useRouter(); const getBusinessHour = useEndpoint('GET', '/v1/livechat/business-hour'); - const { data, isLoading, isError, refetch } = useQuery( - ['livechat-getBusinessHourById', id, type], - async () => getBusinessHour({ _id: id, type }), - { - refetchOnWindowFocus: false, - }, - ); + const { data, isPending, isError, refetch } = useQuery({ + queryKey: ['livechat-getBusinessHourById', id, type], + queryFn: async () => getBusinessHour({ _id: id, type }), + refetchOnWindowFocus: false, + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/omnichannel/components/CustomField.tsx b/apps/meteor/client/views/omnichannel/components/CustomField.tsx index 0d9cc8e386f8..76dfb61ff76e 100644 --- a/apps/meteor/client/views/omnichannel/components/CustomField.tsx +++ b/apps/meteor/client/views/omnichannel/components/CustomField.tsx @@ -14,9 +14,12 @@ type CustomFieldProps = { const CustomField = ({ id, value }: CustomFieldProps) => { const { t } = useTranslation(); const getCustomField = useEndpoint('GET', '/v1/livechat/custom-fields/:_id', { _id: id }); - const { data, isLoading, isError } = useQuery(['/v1/livechat/custom-field', id], () => getCustomField()); + const { data, isPending, isError } = useQuery({ + queryKey: ['/v1/livechat/custom-field', id], + queryFn: () => getCustomField(), + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ContactInfoWithData.tsx b/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ContactInfoWithData.tsx index e1f52bd73259..4eaa3fc8f7eb 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ContactInfoWithData.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ContactInfoWithData.tsx @@ -14,11 +14,13 @@ const ContactInfoWithData = ({ id: contactId, onClose }: ContactInfoWithDataProp const canViewCustomFields = usePermission('view-livechat-room-customfields'); const getContact = useEndpoint('GET', '/v1/omnichannel/contacts.get'); - const { data, isLoading, isError } = useQuery(['getContactById', contactId], () => getContact({ contactId }), { + const { data, isPending, isError } = useQuery({ + queryKey: ['getContactById', contactId], + queryFn: () => getContact({ contactId }), enabled: canViewCustomFields && !!contactId, }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx b/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx index 4aa5a738166e..aabcce1936ff 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx @@ -79,7 +79,7 @@ const EditContactInfo = ({ contactData, onClose, onCancel }: ContactNewEditProps const handleOpenUpSellModal = () => setModal( setModal(null)} />); - const { data: customFieldsMetadata = [], isInitialLoading: isLoadingCustomFields } = useCustomFieldsMetadata({ + const { data: customFieldsMetadata = [], isLoading: isLoadingCustomFields } = useCustomFieldsMetadata({ scope: 'visitor', enabled: canViewCustomFields, }); diff --git a/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfoWithData.tsx b/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfoWithData.tsx index e84ff665af4b..e43cc26ba86e 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfoWithData.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfoWithData.tsx @@ -14,9 +14,12 @@ type EditContactInfoWithDataProps = { const EditContactInfoWithData = ({ id, onClose, onCancel }: EditContactInfoWithDataProps) => { const getContactEndpoint = useEndpoint('GET', '/v1/omnichannel/contacts.get'); - const { data, isLoading, isError } = useQuery(['getContactById', id], async () => getContactEndpoint({ contactId: id })); + const { data, isPending, isError } = useQuery({ + queryKey: ['getContactById', id], + queryFn: async () => getContactEndpoint({ contactId: id }), + }); - if (isLoading) { + if (isPending) { return ( diff --git a/apps/meteor/client/views/omnichannel/contactInfo/hooks/useCustomFieldsQuery.ts b/apps/meteor/client/views/omnichannel/contactInfo/hooks/useCustomFieldsQuery.ts index 96dd27a6d07c..c714915166dc 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/hooks/useCustomFieldsQuery.ts +++ b/apps/meteor/client/views/omnichannel/contactInfo/hooks/useCustomFieldsQuery.ts @@ -4,5 +4,5 @@ import { useQuery } from '@tanstack/react-query'; // TODO: Unify this hook with all the other with the same proposal export const useCustomFieldsQuery = () => { const getCustomFields = useEndpoint('GET', '/v1/livechat/custom-fields'); - return useQuery(['/v1/livechat/custom-fields'], async () => getCustomFields()); + return useQuery({ queryKey: ['/v1/livechat/custom-fields'], queryFn: async () => getCustomFields() }); }; diff --git a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannels.tsx b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannels.tsx index 8ee167357153..7a9ab6c6e804 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannels.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/ContactInfoChannels.tsx @@ -17,9 +17,12 @@ const ContactInfoChannels = ({ contactId }: ContactInfoChannelsProps) => { const { t } = useTranslation(); const getContactChannels = useEndpoint('GET', '/v1/omnichannel/contacts.channels'); - const { data, isError, isLoading } = useQuery(['getContactChannels', contactId], () => getContactChannels({ contactId })); + const { data, isError, isPending } = useQuery({ + queryKey: ['getContactChannels', contactId], + queryFn: () => getContactChannels({ contactId }), + }); - if (isLoading) { + if (isPending) { return ( diff --git a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx index 6a126250e46c..a647c7782d54 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx @@ -22,7 +22,7 @@ export const useBlockChannel = ({ blocked, association }: { blocked: boolean; as try { await unblockContact({ visitor: association }); dispatchToastMessage({ type: 'success', message: t('Contact_unblocked') }); - queryClient.invalidateQueries(['getContactById']); + queryClient.invalidateQueries({ queryKey: ['getContactById'] }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } @@ -37,7 +37,7 @@ export const useBlockChannel = ({ blocked, association }: { blocked: boolean; as try { await blockContact({ visitor: association }); dispatchToastMessage({ type: 'success', message: t('Contact_blocked') }); - queryClient.invalidateQueries(['getContactById']); + queryClient.invalidateQueries({ queryKey: ['getContactById'] }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } finally { diff --git a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactManagerInfo.tsx b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactManagerInfo.tsx index c80aea690d6f..177e3e24dd9d 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactManagerInfo.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoDetails/ContactManagerInfo.tsx @@ -12,7 +12,10 @@ const ContactManagerInfo = ({ userId }: ContactManagerInfoProps) => { const { t } = useTranslation(); const getContactManagerByUsername = useEndpoint('GET', '/v1/users.info'); - const { data, isLoading, isError } = useQuery(['getContactManagerByUserId', userId], async () => getContactManagerByUsername({ userId })); + const { data, isLoading, isSuccess, isError } = useQuery({ + queryKey: ['getContactManagerByUserId', userId], + queryFn: async () => getContactManagerByUsername({ userId }), + }); if (isError) { return null; @@ -22,7 +25,7 @@ const ContactManagerInfo = ({ userId }: ContactManagerInfoProps) => { {t('Contact_Manager')} {isLoading && } - {!isLoading && ( + {isSuccess && ( {data.user.username && } diff --git a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx index cddd4643b9a0..ab1c719a1fde 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx @@ -34,9 +34,10 @@ const ContactInfoHistory = ({ contact, setChatId }: ContactInfoHistoryProps) => const { getSourceName } = useOmnichannelSource(); const getContactHistory = useEndpoint('GET', '/v1/omnichannel/contacts.history'); - const { data, isLoading, isError } = useQuery(['getContactHistory', contact._id, type], () => - getContactHistory({ contactId: contact._id, source: type === 'all' ? undefined : type }), - ); + const { data, isLoading, isError } = useQuery({ + queryKey: ['getContactHistory', contact._id, type], + queryFn: () => getContactHistory({ contactId: contact._id, source: type === 'all' ? undefined : type }), + }); const handleChangeFilter = (value: Key) => { if (isFilterBlocked(hasLicense, value)) { diff --git a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx index f84e9a57f8a8..d7c4bef80a12 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx +++ b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx @@ -3,7 +3,7 @@ import { Callout, Pagination } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import type { GETLivechatRoomsParams } from '@rocket.chat/rest-typings'; import { usePermission, useRouter } from '@rocket.chat/ui-contexts'; -import { hashQueryKey } from '@tanstack/react-query'; +import { hashKey } from '@tanstack/react-query'; import moment from 'moment'; import type { ComponentProps, ReactElement } from 'react'; import { memo, useCallback, useMemo, useState } from 'react'; @@ -164,8 +164,8 @@ const CurrentChatsPage = ({ id, onRowClick }: { id?: string; onRowClick: (_id: s const { data, isLoading, isSuccess } = useCurrentChats(query); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const onFilter = useMutableCallback((params: DebouncedParams): void => { setParams(params); diff --git a/apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx b/apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx index e5d94e7cd28f..a1daa91b9014 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx +++ b/apps/meteor/client/views/omnichannel/currentChats/RemoveChatButton.tsx @@ -41,7 +41,7 @@ const RemoveChatButton = ({ _id }: RemoveChatButtonProps) => { ); }); - return ; + return ; }; export default RemoveChatButton; diff --git a/apps/meteor/client/views/omnichannel/currentChats/hooks/useAllCustomFields.tsx b/apps/meteor/client/views/omnichannel/currentChats/hooks/useAllCustomFields.tsx index d6987786eba9..2b66d8822b65 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/hooks/useAllCustomFields.tsx +++ b/apps/meteor/client/views/omnichannel/currentChats/hooks/useAllCustomFields.tsx @@ -6,5 +6,8 @@ import { useQuery } from '@tanstack/react-query'; export const useAllCustomFields = (): UseQueryResult> => { const allCustomFields = useEndpoint('GET', '/v1/livechat/custom-fields'); - return useQuery(['livechat/custom-fields'], async () => allCustomFields()); + return useQuery({ + queryKey: ['livechat/custom-fields'], + queryFn: async () => allCustomFields(), + }); }; diff --git a/apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts b/apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts index 4f3696709549..cee4e5d7979e 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts +++ b/apps/meteor/client/views/omnichannel/currentChats/hooks/useCurrentChats.ts @@ -9,9 +9,13 @@ export const useCurrentChats = (query: GETLivechatRoomsParams): UseQueryResult currentChats(debouncedQuery), { + return useQuery({ + queryKey: ['current-chats', debouncedQuery], + queryFn: () => currentChats(debouncedQuery), + // TODO: Update this to use an stream of room changes instead of polling refetchOnWindowFocus: false, - cacheTime: 0, + + gcTime: 0, }); }; diff --git a/apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts b/apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts index 97a8dccbf938..be59e98b2677 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts +++ b/apps/meteor/client/views/omnichannel/currentChats/hooks/useRemoveCurrentChatMutation.ts @@ -9,10 +9,14 @@ export const useRemoveCurrentChatMutation = ( const removeRoom = useMethod('livechat:removeRoom'); const queryClient = useQueryClient(); - return useMutation((rid) => removeRoom(rid), { + return useMutation({ + mutationFn: (rid) => removeRoom(rid), ...options, + onSuccess: (...args) => { - queryClient.invalidateQueries(['current-chats']); + queryClient.invalidateQueries({ + queryKey: ['current-chats'], + }); options?.onSuccess?.(...args); }, }); diff --git a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx b/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx index 649d982d9343..3ec457ffe988 100644 --- a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx +++ b/apps/meteor/client/views/omnichannel/customFields/CustomFieldsTable.tsx @@ -1,7 +1,7 @@ import { IconButton, Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useEndpoint, useRouter } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useQuery, hashKey } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import { useRemoveCustomField } from './useRemoveCustomField'; @@ -46,10 +46,13 @@ const CustomFieldsTable = () => { ); const getCustomFields = useEndpoint('GET', '/v1/livechat/custom-fields'); - const { data, isSuccess, isLoading } = useQuery(['livechat-customFields', query], async () => getCustomFields(query)); + const { data, isSuccess, isLoading } = useQuery({ + queryKey: ['livechat-customFields', query], + queryFn: async () => getCustomFields(query), + }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/views/omnichannel/customFields/EditCustomFields.tsx b/apps/meteor/client/views/omnichannel/customFields/EditCustomFields.tsx index 935596a8d3cf..16c0feaa8e4f 100644 --- a/apps/meteor/client/views/omnichannel/customFields/EditCustomFields.tsx +++ b/apps/meteor/client/views/omnichannel/customFields/EditCustomFields.tsx @@ -70,7 +70,9 @@ const EditCustomFields = ({ customFieldData }: { customFieldData?: Serialized getCustomFieldById(), { + const { data, isPending, isError } = useQuery({ + queryKey: ['livechat-getCustomFieldsById', customFieldId], + queryFn: async () => getCustomFieldById(), refetchOnWindowFocus: false, }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/omnichannel/customFields/useRemoveCustomField.tsx b/apps/meteor/client/views/omnichannel/customFields/useRemoveCustomField.tsx index f71d44949f6e..eafb2b35956f 100644 --- a/apps/meteor/client/views/omnichannel/customFields/useRemoveCustomField.tsx +++ b/apps/meteor/client/views/omnichannel/customFields/useRemoveCustomField.tsx @@ -17,7 +17,9 @@ export const useRemoveCustomField = () => { try { await removeCustomField(id); dispatchToastMessage({ type: 'success', message: t('Custom_Field_Removed') }); - queryClient.invalidateQueries(['livechat-customFields']); + queryClient.invalidateQueries({ + queryKey: ['livechat-customFields'], + }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); } finally { diff --git a/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentItemMenu.tsx b/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentItemMenu.tsx index ade4dfbb07b7..ce5fe853dc73 100644 --- a/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentItemMenu.tsx +++ b/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentItemMenu.tsx @@ -37,14 +37,18 @@ const DepartmentItemMenu = ({ department, archived }: DepartmentItemMenuProps): }); const handleReload = useCallback(async () => { - await queryClient.invalidateQueries(['livechat-departments']); + await queryClient.invalidateQueries({ + queryKey: ['livechat-departments'], + }); }, [queryClient]); const handleToggleArchive = useMutableCallback(async () => { try { await toggleArchive(); dispatchToastMessage({ type: 'success', message: archived ? t('Department_unarchived') : t('Department_archived') }); - queryClient.removeQueries(['/v1/livechat/department/:_id', department._id]); + queryClient.removeQueries({ + queryKey: ['/v1/livechat/department/:_id', department._id], + }); handleReload(); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); diff --git a/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentsTable.tsx b/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentsTable.tsx index 5cb1324dc7e2..baf48927a266 100644 --- a/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentsTable.tsx +++ b/apps/meteor/client/views/omnichannel/departments/DepartmentsTable/DepartmentsTable.tsx @@ -2,7 +2,7 @@ import type { ILivechatDepartment } from '@rocket.chat/core-typings'; import { Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useEndpoint, useRouter } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useQuery, hashKey, keepPreviousData } from '@tanstack/react-query'; import { useState, useMemo } from 'react'; import DepartmentItemMenu from './DepartmentItemMenu'; @@ -51,12 +51,14 @@ const DepartmentsTable = ({ archived }: { archived: boolean }) => { 500, ); - const { data, isSuccess, isLoading } = useQuery(['livechat-departments', query, archived], async () => getDepartments(query), { - keepPreviousData: true, + const { data, isSuccess, isLoading } = useQuery({ + queryKey: ['livechat-departments', query, archived], + queryFn: async () => getDepartments(query), + placeholderData: keepPreviousData, }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx b/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx index 56f533f92613..cbd9b6587a56 100644 --- a/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx +++ b/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx @@ -198,7 +198,9 @@ function EditDepartment({ data, id, title, allowedToForwardData }: EditDepartmen } else { await saveDepartmentInfo(id ?? null, payload, agentList); } - queryClient.invalidateQueries(['/v1/livechat/department/:_id', id]); + queryClient.invalidateQueries({ + queryKey: ['/v1/livechat/department/:_id', id], + }); dispatchToastMessage({ type: 'success', message: t('Saved') }); router.navigate('/omnichannel/departments'); } catch (error) { diff --git a/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithAllowedForwardData.tsx b/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithAllowedForwardData.tsx index 207ce210e0ba..b9a0da934237 100644 --- a/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithAllowedForwardData.tsx +++ b/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithAllowedForwardData.tsx @@ -13,15 +13,18 @@ const EditDepartmentWithAllowedForwardData = ({ data, ...props }: Omit - getDepartmentListByIds({ - ids: data?.department?.departmentsAllowedToForward ?? [], - }), - ); + } = useQuery({ + queryKey: ['/v1/livechat/department.listByIds', data?.department?.departmentsAllowedToForward], - if (isInitialLoading) { + queryFn: () => + getDepartmentListByIds({ + ids: data?.department?.departmentsAllowedToForward ?? [], + }), + }); + + if (isLoading) { return ; } diff --git a/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithData.tsx b/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithData.tsx index b38d3fe0d9b0..692a4ffbbf60 100644 --- a/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithData.tsx +++ b/apps/meteor/client/views/omnichannel/departments/EditDepartmentWithData.tsx @@ -17,11 +17,13 @@ type EditDepartmentWithDataProps = { const EditDepartmentWithData = ({ id, title }: EditDepartmentWithDataProps) => { const { t } = useTranslation(); const getDepartment = useEndpoint('GET', '/v1/livechat/department/:_id', { _id: id ?? '' }); - const { data, isInitialLoading, isError } = useQuery(['/v1/livechat/department/:_id', id], () => getDepartment(params), { + const { data, isLoading, isError } = useQuery({ + queryKey: ['/v1/livechat/department/:_id', id], + queryFn: () => getDepartment(params), enabled: !!id, }); - if (isInitialLoading) { + if (isLoading) { return ; } diff --git a/apps/meteor/client/views/omnichannel/departments/NewDepartment.tsx b/apps/meteor/client/views/omnichannel/departments/NewDepartment.tsx index 0ddac50eb892..1cc3cb7236d6 100644 --- a/apps/meteor/client/views/omnichannel/departments/NewDepartment.tsx +++ b/apps/meteor/client/views/omnichannel/departments/NewDepartment.tsx @@ -1,6 +1,7 @@ import { Callout } from '@rocket.chat/fuselage'; import { useEndpoint, useSetModal } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import EditDepartment from './EditDepartment'; @@ -15,19 +16,22 @@ const NewDepartment = ({ id }: NewDepartmentProps) => { const { t } = useTranslation(); const setModal = useSetModal(); const getDepartmentCreationAvailable = useEndpoint('GET', '/v1/livechat/department/isDepartmentCreationAvailable'); - const { data, isLoading, isError } = useQuery(['getDepartments'], () => getDepartmentCreationAvailable(), { - onSuccess: (data) => { - if (data.isDepartmentCreationAvailable === false) { - setModal( setModal(null)} />); - } - }, + const { data, isPending, isError } = useQuery({ + queryKey: ['getDepartments'], + queryFn: () => getDepartmentCreationAvailable(), }); + useEffect(() => { + if (data?.isDepartmentCreationAvailable === false) { + setModal( setModal(null)} />); + } + }, [data?.isDepartmentCreationAvailable, setModal]); + if (isError) { return {t('Unavailable')}; } - if (!data || isLoading || !data.isDepartmentCreationAvailable) { + if (!data || isPending || !data.isDepartmentCreationAvailable) { return ; } diff --git a/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx b/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx index 0e1f2b9443d5..5ef2e8a8ab98 100644 --- a/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx +++ b/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx @@ -1,7 +1,7 @@ import { Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useRoute, useTranslation, useEndpoint, useUserId } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useQuery, hashKey } from '@tanstack/react-query'; import { useState, useMemo } from 'react'; import { CallTableRow } from './CallTableRow'; @@ -53,10 +53,13 @@ const CallTable = () => { }); const getVoipRooms = useEndpoint('GET', '/v1/voip/rooms'); - const { data, isSuccess, isLoading } = useQuery(['voip-rooms', query], async () => getVoipRooms(query)); + const { data, isSuccess, isLoading } = useQuery({ + queryKey: ['voip-rooms', query], + queryFn: async () => getVoipRooms(query), + }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEdit.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEdit.tsx index fbfcd222cf0e..b16e73228513 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEdit.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEdit.tsx @@ -50,8 +50,8 @@ function RoomEdit({ room, visitor, reload, reloadInfo, onClose }: RoomEditProps) const saveRoom = useEndpoint('POST', '/v1/livechat/room.saveInfo'); - const { data: slaPolicies, isInitialLoading: isSlaPoliciesLoading } = useSlaPolicies(); - const { data: customFieldsMetadata, isInitialLoading: isCustomFieldsLoading } = useCustomFieldsMetadata({ + const { data: slaPolicies, isLoading: isSlaPoliciesLoading } = useSlaPolicies(); + const { data: customFieldsMetadata, isLoading: isCustomFieldsLoading } = useCustomFieldsMetadata({ scope: 'room', enabled: canViewCustomFields, }); @@ -94,7 +94,9 @@ function RoomEdit({ room, visitor, reload, reloadInfo, onClose }: RoomEditProps) try { await saveRoom({ guestData, roomData }); - await queryClient.invalidateQueries(['/v1/rooms.info', room._id]); + await queryClient.invalidateQueries({ + queryKey: ['/v1/rooms.info', room._id], + }); dispatchToastMessage({ type: 'success', message: t('Saved') }); reload?.(); diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEditWithData.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEditWithData.tsx index 1146e67673cd..23db25d60853 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEditWithData.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatInfo/RoomEdit/RoomEditWithData.tsx @@ -19,11 +19,7 @@ function RoomEditWithData({ id: roomId, reload, reloadInfo, onClose }: RoomEditW const { data: room, isLoading: isRoomLoading, isError: isRoomError } = useOmnichannelRoomInfo(roomId); const { _id: visitorId } = room?.v ?? {}; - const { - data: visitor, - isInitialLoading: isVisitorLoading, - isError: isVisitorError, - } = useVisitorInfo(visitorId, { enabled: !!visitorId }); + const { data: visitor, isLoading: isVisitorLoading, isError: isVisitorError } = useVisitorInfo(visitorId, { enabled: !!visitorId }); if (isRoomLoading || isVisitorLoading) { return ; diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx index 8b760b9d2e8b..9319d834169f 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx @@ -29,7 +29,7 @@ const ChatsFiltersContextualBar = ({ onClose }: ChatsFiltersContextualBarProps) const canViewCustomFields = usePermission('view-livechat-room-customfields'); const allCustomFields = useEndpoint('GET', '/v1/livechat/custom-fields'); - const { data } = useQuery(['livechat/custom-fields'], async () => allCustomFields()); + const { data } = useQuery({ queryKey: ['livechat/custom-fields'], queryFn: async () => allCustomFields() }); const contactCustomFields = data?.customFields.filter((customField) => customField.scope !== 'visitor'); const { filtersQuery, setFiltersQuery, resetFiltersQuery, hasAppliedFilters } = useChatsContext(); @@ -49,7 +49,7 @@ const ChatsFiltersContextualBar = ({ onClose }: ChatsFiltersContextualBarProps) const handleSubmitFilters = (data: ChatsFiltersQuery) => { setFiltersQuery(({ guest }) => ({ ...data, guest })); - queryClient.invalidateQueries(['current-chats']); + queryClient.invalidateQueries({ queryKey: ['current-chats'] }); }; const handleResetFilters = () => { diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx index af061fae3110..d27ca5b0aaf0 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTable.tsx @@ -1,6 +1,6 @@ import { Pagination, States, StatesIcon, StatesTitle, StatesActions, StatesAction } from '@rocket.chat/fuselage'; import { usePermission } from '@rocket.chat/ui-contexts'; -import { hashQueryKey } from '@tanstack/react-query'; +import { hashKey } from '@tanstack/react-query'; import { useState, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -42,8 +42,8 @@ const ChatsTable = () => { const { data, isLoading, isSuccess, isError, refetch } = useCurrentChats(query); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx index 72fad380aab7..d4f0a398d939 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatsTable/ChatsTableFilter.tsx @@ -23,7 +23,7 @@ const ChatsTableFilter = () => { const onDeleteAll = async () => { try { await removeClosedChats(); - queryClient.invalidateQueries(['current-chats']); + queryClient.invalidateQueries({ queryKey: ['current-chats'] }); dispatchToastMessage({ type: 'success', message: t('Chat_removed') }); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); diff --git a/apps/meteor/client/views/omnichannel/directory/components/AgentField.tsx b/apps/meteor/client/views/omnichannel/directory/components/AgentField.tsx index b58a353f52dc..653251e23f85 100644 --- a/apps/meteor/client/views/omnichannel/directory/components/AgentField.tsx +++ b/apps/meteor/client/views/omnichannel/directory/components/AgentField.tsx @@ -20,7 +20,10 @@ const AgentField = ({ agent, isSmall = false }: AgentFieldProps) => { const { t } = useTranslation(); const { username = '' } = agent ?? {}; const getUserInfo = useEndpoint('GET', '/v1/users.info'); - const { data, isLoading } = useQuery(['/v1/users.info', username], () => getUserInfo({ username })); + const { data, isLoading } = useQuery({ + queryKey: ['/v1/users.info', username], + queryFn: () => getUserInfo({ username }), + }); if (isLoading) { return ; diff --git a/apps/meteor/client/views/omnichannel/directory/components/ContactField.tsx b/apps/meteor/client/views/omnichannel/directory/components/ContactField.tsx index 068bacd74615..74892f7442e5 100644 --- a/apps/meteor/client/views/omnichannel/directory/components/ContactField.tsx +++ b/apps/meteor/client/views/omnichannel/directory/components/ContactField.tsx @@ -24,11 +24,13 @@ const ContactField = ({ contact, room }: ContactFieldProps) => { const avatarUrl = roomCoordinator.getRoomDirectives(type).getAvatarPath(room) || ''; const getVisitorInfo = useEndpoint('GET', '/v1/livechat/visitors.info'); - const { data, isLoading, isError } = useQuery(['/v1/livechat/visitors.info', contact._id], () => - getVisitorInfo({ visitorId: contact._id }), - ); + const { data, isPending, isError } = useQuery({ + queryKey: ['/v1/livechat/visitors.info', contact._id], + + queryFn: () => getVisitorInfo({ visitorId: contact._id }), + }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/omnichannel/directory/components/PriorityField.tsx b/apps/meteor/client/views/omnichannel/directory/components/PriorityField.tsx index b8eaf28ca8d7..503f2172b008 100644 --- a/apps/meteor/client/views/omnichannel/directory/components/PriorityField.tsx +++ b/apps/meteor/client/views/omnichannel/directory/components/PriorityField.tsx @@ -13,9 +13,9 @@ type PriorityFieldProps = { const PriorityField = ({ id }: PriorityFieldProps) => { const { t } = useTranslation(); - const { data, isInitialLoading, isError } = usePriorityInfo(id); + const { data, isLoading, isError } = usePriorityInfo(id); - if (isInitialLoading) { + if (isLoading) { return ; } diff --git a/apps/meteor/client/views/omnichannel/directory/components/SlaField.tsx b/apps/meteor/client/views/omnichannel/directory/components/SlaField.tsx index 5a957becf2ba..0272c2dcd501 100644 --- a/apps/meteor/client/views/omnichannel/directory/components/SlaField.tsx +++ b/apps/meteor/client/views/omnichannel/directory/components/SlaField.tsx @@ -13,9 +13,9 @@ type SlaFieldProps = { const SlaField = ({ id }: SlaFieldProps) => { const { t } = useTranslation(); - const { data, isInitialLoading, isError } = useSlaInfo(id); + const { data, isLoading, isError } = useSlaInfo(id); - if (isInitialLoading) { + if (isLoading) { return ; } diff --git a/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx b/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx index 0bc9aa598b12..2035de375c9f 100644 --- a/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx +++ b/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx @@ -1,7 +1,7 @@ import { Pagination, States, StatesAction, StatesActions, StatesIcon, StatesTitle, Box, Button } from '@rocket.chat/fuselage'; import { useDebouncedValue, useEffectEvent } from '@rocket.chat/fuselage-hooks'; import { useRoute } from '@rocket.chat/ui-contexts'; -import { hashQueryKey } from '@tanstack/react-query'; +import { hashKey } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -52,8 +52,8 @@ function ContactTable() { const { data, isLoading, isError, isSuccess, refetch } = useCurrentContacts(query); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/views/omnichannel/directory/contacts/hooks/useCurrentContacts.ts b/apps/meteor/client/views/omnichannel/directory/contacts/hooks/useCurrentContacts.ts index b7f1ac7866c1..f5004f23da53 100644 --- a/apps/meteor/client/views/omnichannel/directory/contacts/hooks/useCurrentContacts.ts +++ b/apps/meteor/client/views/omnichannel/directory/contacts/hooks/useCurrentContacts.ts @@ -10,5 +10,8 @@ export const useCurrentContacts = ( ): UseQueryResult> => { const currentContacts = useEndpoint('GET', '/v1/omnichannel/contacts.search'); - return useQuery(['current-contacts', query], () => currentContacts(query)); + return useQuery({ + queryKey: ['current-contacts', query], + queryFn: () => currentContacts(query), + }); }; diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useCustomFieldsMetadata.tsx b/apps/meteor/client/views/omnichannel/directory/hooks/useCustomFieldsMetadata.tsx index b08d56f0f0f2..85437af895a0 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useCustomFieldsMetadata.tsx +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useCustomFieldsMetadata.tsx @@ -10,12 +10,14 @@ type UseCustomFieldsMetadataOptions = { export const useCustomFieldsMetadata = ({ enabled = true, scope }: UseCustomFieldsMetadataOptions) => { const getCustomFields = useEndpoint('GET', '/v1/livechat/custom-fields'); - return useQuery( - ['/v1/livechat/custom-fields', scope], - async () => { + return useQuery({ + queryKey: ['/v1/livechat/custom-fields', scope], + + queryFn: async () => { const { customFields } = (await getCustomFields()) ?? {}; return formatCustomFieldsMetadata(customFields, scope); }, - { enabled }, - ); + + enabled, + }); }; diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useDepartmentInfo.ts b/apps/meteor/client/views/omnichannel/directory/hooks/useDepartmentInfo.ts index 076d794567b3..b08df7480875 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useDepartmentInfo.ts +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useDepartmentInfo.ts @@ -6,5 +6,8 @@ import { useQuery } from '@tanstack/react-query'; export const useDepartmentInfo = (departmentId: string): UseQueryResult> => { const deptInfo = useEndpoint('GET', `/v1/livechat/department/:_id`, { _id: departmentId }); - return useQuery(['livechat/department', departmentId], () => deptInfo({})); + return useQuery({ + queryKey: ['livechat/department', departmentId], + queryFn: () => deptInfo({}), + }); }; diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useDisplayFilters.ts b/apps/meteor/client/views/omnichannel/directory/hooks/useDisplayFilters.ts index a02660ea7510..e789d50cb5c5 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useDisplayFilters.ts +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useDisplayFilters.ts @@ -23,8 +23,8 @@ export const useDisplayFilters = (filtersQuery: ChatsFiltersQuery) => { const getDepartment = useEndpoint('GET', '/v1/livechat/department/:_id', { _id: department }); const getAgent = useEndpoint('GET', '/v1/livechat/users/agent/:_id', { _id: servedBy }); - const { data: departmentData } = useQuery(['getDepartmentDataForFilter', department], () => getDepartment({})); - const { data: agentData } = useQuery(['getAgentDataForFilter', servedBy], () => getAgent()); + const { data: departmentData } = useQuery({ queryKey: ['getDepartmentDataForFilter', department], queryFn: () => getDepartment({}) }); + const { data: agentData } = useQuery({ queryKey: ['getAgentDataForFilter', servedBy], queryFn: () => getAgent() }); const displayCustomFields = Object.entries(customFields).reduce( (acc, [key, value]) => { diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/usePriorityInfo.tsx b/apps/meteor/client/views/omnichannel/directory/hooks/usePriorityInfo.tsx index e30d352bcba2..957110b6a58e 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/usePriorityInfo.tsx +++ b/apps/meteor/client/views/omnichannel/directory/hooks/usePriorityInfo.tsx @@ -12,8 +12,10 @@ type ILivechatClientPriority = Serialized & { export const usePriorityInfo = (priorityId: string) => { const { enabled } = useOmnichannelPriorities(); const getPriority = useEndpoint('GET', `/v1/livechat/priorities/:priorityId`, { priorityId }); - return useQuery(['/v1/livechat/priorities', priorityId], () => getPriority() as Promise, { - cacheTime: 0, + return useQuery({ + queryKey: ['/v1/livechat/priorities', priorityId], + queryFn: () => getPriority() as Promise, + gcTime: 0, enabled, }); }; diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx index f1655fb16309..60d8c270d5df 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx @@ -6,7 +6,9 @@ import { useHasLicenseModule } from '../../../../hooks/useHasLicenseModule'; export const useSlaInfo = (slaId: string) => { const isEnterprise = useHasLicenseModule('livechat-enterprise') === true; const getSLA = useEndpoint('GET', '/v1/livechat/sla/:slaId', { slaId }); - return useQuery(['/v1/livechat/sla/:slaId', slaId], () => getSLA(), { + return useQuery({ + queryKey: ['/v1/livechat/sla/:slaId', slaId], + queryFn: () => getSLA(), enabled: isEnterprise && !!slaId, }); }; diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx index bbf222f76310..4c05262c7a1a 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx @@ -7,7 +7,9 @@ import { useHasLicenseModule } from '../../../../hooks/useHasLicenseModule'; export const useSlaPolicies = () => { const isEnterprise = useHasLicenseModule('livechat-enterprise') === true; const getSlaPolicies = useEndpoint('GET', '/v1/livechat/sla'); - const { data: { sla } = {}, ...props } = useQuery(['/v1/livechat/sla'], () => getSlaPolicies({}), { + const { data: { sla } = {}, ...props } = useQuery({ + queryKey: ['/v1/livechat/sla'], + queryFn: () => getSlaPolicies({}), staleTime: millisecondsToMinutes(10), enabled: isEnterprise, }); diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useVisitorInfo.tsx b/apps/meteor/client/views/omnichannel/directory/hooks/useVisitorInfo.tsx index 102df6d34609..48e2de1f230b 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useVisitorInfo.tsx +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useVisitorInfo.tsx @@ -1,11 +1,13 @@ import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; -export const useVisitorInfo = (visitorId: string, { enabled = true, cacheTime = 0 } = {}) => { +export const useVisitorInfo = (visitorId: string, { enabled = true, gcTime = 0 } = {}) => { const getVisitorInfo = useEndpoint('GET', '/v1/livechat/visitors.info'); - const { data: { visitor } = {}, ...props } = useQuery(['/v1/livechat/visitors.info', visitorId], () => getVisitorInfo({ visitorId }), { + const { data: { visitor } = {}, ...props } = useQuery({ + queryKey: ['/v1/livechat/visitors.info', visitorId], + queryFn: () => getVisitorInfo({ visitorId }), enabled, - cacheTime, + gcTime, }); return { data: visitor, ...props }; }; diff --git a/apps/meteor/client/views/omnichannel/managers/ManagersTable.tsx b/apps/meteor/client/views/omnichannel/managers/ManagersTable.tsx index e09a133ec205..0d13a1543b0f 100644 --- a/apps/meteor/client/views/omnichannel/managers/ManagersTable.tsx +++ b/apps/meteor/client/views/omnichannel/managers/ManagersTable.tsx @@ -2,7 +2,7 @@ import { Box, Pagination } from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { UserAvatar } from '@rocket.chat/ui-avatar'; import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; -import { hashQueryKey, useQuery } from '@tanstack/react-query'; +import { hashKey, useQuery } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import AddManager from './AddManager'; @@ -45,12 +45,14 @@ const ManagersTable = () => { ); const getManagers = useEndpoint('GET', '/v1/livechat/users/manager'); - const { data, isLoading, isSuccess, refetch } = useQuery(['omnichannel', 'managers', 'livechat-manager', query], async () => - getManagers(query), - ); + const { data, isLoading, isSuccess, refetch } = useQuery({ + queryKey: ['omnichannel', 'managers', 'livechat-manager', query], + + queryFn: async () => getManagers(query), + }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx b/apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx index 8ab3609dd469..e57fa1612cec 100644 --- a/apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx +++ b/apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx @@ -109,7 +109,10 @@ const QueueListTable = (): ReactElement => { }; const getLivechatQueue = useEndpoint('GET', '/v1/livechat/queue'); - const { data, isSuccess, isLoading } = useQuery(['livechat-queue', query], async () => getLivechatQueue(query)); + const { data, isSuccess, isLoading } = useQuery({ + queryKey: ['livechat-queue', query], + queryFn: async () => getLivechatQueue(query), + }); return ( <> diff --git a/apps/meteor/client/views/omnichannel/triggers/EditTrigger.tsx b/apps/meteor/client/views/omnichannel/triggers/EditTrigger.tsx index 7a3a5de7b81f..aeaeb0d3fda1 100644 --- a/apps/meteor/client/views/omnichannel/triggers/EditTrigger.tsx +++ b/apps/meteor/client/views/omnichannel/triggers/EditTrigger.tsx @@ -114,8 +114,12 @@ const EditTrigger = ({ triggerData }: { triggerData?: Serialized { dispatchToastMessage({ type: 'success', message: t('Saved') }); - queryClient.invalidateQueries(['livechat-getTriggersById']); - queryClient.invalidateQueries(['livechat-triggers']); + queryClient.invalidateQueries({ + queryKey: ['livechat-getTriggersById'], + }); + queryClient.invalidateQueries({ + queryKey: ['livechat-triggers'], + }); router.navigate('/omnichannel/triggers'); }, onError: (error) => { diff --git a/apps/meteor/client/views/omnichannel/triggers/EditTriggerWithData.tsx b/apps/meteor/client/views/omnichannel/triggers/EditTriggerWithData.tsx index 5df91471d8c0..df4dfd2d1942 100644 --- a/apps/meteor/client/views/omnichannel/triggers/EditTriggerWithData.tsx +++ b/apps/meteor/client/views/omnichannel/triggers/EditTriggerWithData.tsx @@ -10,11 +10,13 @@ import { ContextualbarSkeleton } from '../../../components/Contextualbar'; const EditTriggerWithData = ({ triggerId }: { triggerId: ILivechatTrigger['_id'] }) => { const { t } = useTranslation(); const getTriggersById = useEndpoint('GET', '/v1/livechat/triggers/:_id', { _id: triggerId }); - const { data, isLoading, isError } = useQuery(['livechat-getTriggersById', triggerId], async () => getTriggersById(), { + const { data, isPending, isError } = useQuery({ + queryKey: ['livechat-getTriggersById', triggerId], + queryFn: async () => getTriggersById(), refetchOnWindowFocus: false, }); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/omnichannel/triggers/TriggersTable.tsx b/apps/meteor/client/views/omnichannel/triggers/TriggersTable.tsx index 556122c5bcfb..22e9418f37ce 100644 --- a/apps/meteor/client/views/omnichannel/triggers/TriggersTable.tsx +++ b/apps/meteor/client/views/omnichannel/triggers/TriggersTable.tsx @@ -1,7 +1,7 @@ import { Pagination } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useEndpoint, useRouter } from '@rocket.chat/ui-contexts'; -import { useQuery, hashQueryKey } from '@tanstack/react-query'; +import { useQuery, hashKey } from '@tanstack/react-query'; import { useMemo, useState } from 'react'; import TriggersRow from './TriggersRow'; @@ -29,10 +29,13 @@ const TriggersTable = () => { const query = useMemo(() => ({ offset: current, count: itemsPerPage }), [current, itemsPerPage]); const getTriggers = useEndpoint('GET', '/v1/livechat/triggers'); - const { data, refetch, isSuccess, isLoading, isError } = useQuery(['livechat-triggers', query], async () => getTriggers(query)); + const { data, refetch, isSuccess, isLoading, isError } = useQuery({ + queryKey: ['livechat-triggers', query], + queryFn: async () => getTriggers(query), + }); - const [defaultQuery] = useState(hashQueryKey([query])); - const queryHasChanged = defaultQuery !== hashQueryKey([query]); + const [defaultQuery] = useState(hashKey([query])); + const queryHasChanged = defaultQuery !== hashKey([query]); const headers = ( <> diff --git a/apps/meteor/client/views/omnichannel/triggers/actions/ActionExternalServiceUrl.tsx b/apps/meteor/client/views/omnichannel/triggers/actions/ActionExternalServiceUrl.tsx index 97311668927d..ef9dac0025a5 100644 --- a/apps/meteor/client/views/omnichannel/triggers/actions/ActionExternalServiceUrl.tsx +++ b/apps/meteor/client/views/omnichannel/triggers/actions/ActionExternalServiceUrl.tsx @@ -75,7 +75,7 @@ export const ActionExternalServiceUrl = ({ control, trigger, index, disabled, .. deps: serviceTimeoutFieldName, }} render={({ field }) => { - return ; + return ; }} /> @@ -84,7 +84,7 @@ export const ActionExternalServiceUrl = ({ control, trigger, index, disabled, .. {t('External_service_test_hint')} - @@ -125,7 +125,7 @@ const OutlookEventsList = ({ onClose, changeRoute }: OutlookEventsListProps): Re {hasOutlookMethods && ( - diff --git a/apps/meteor/client/views/outlookCalendar/hooks/useOutlookAuthentication.ts b/apps/meteor/client/views/outlookCalendar/hooks/useOutlookAuthentication.ts index 29d6515759fc..cc343ee26f67 100644 --- a/apps/meteor/client/views/outlookCalendar/hooks/useOutlookAuthentication.ts +++ b/apps/meteor/client/views/outlookCalendar/hooks/useOutlookAuthentication.ts @@ -9,9 +9,10 @@ export const useOutlookAuthentication = () => { data: authEnabled, isError, error, - } = useQuery( - ['outlook', 'auth'], - async () => { + } = useQuery({ + queryKey: ['outlook', 'auth'], + + queryFn: async () => { const desktopApp = window.RocketChatDesktop; if (!desktopApp?.hasOutlookCredentials) { throw new NotOnDesktopError(); @@ -19,12 +20,7 @@ export const useOutlookAuthentication = () => { return Boolean(await desktopApp?.hasOutlookCredentials?.()) || false; }, - { - onError: (error) => { - console.error(error); - }, - }, - ); + }); return { authEnabled: Boolean(authEnabled), isError, error }; }; @@ -33,7 +29,9 @@ export const useOutlookAuthenticationMutation = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async () => { - await queryClient.invalidateQueries(['outlook', 'auth']); + await queryClient.invalidateQueries({ + queryKey: ['outlook', 'auth'], + }); }, }); }; diff --git a/apps/meteor/client/views/outlookCalendar/hooks/useOutlookCalendarList.ts b/apps/meteor/client/views/outlookCalendar/hooks/useOutlookCalendarList.ts index 980d087a2370..372f68352d9d 100644 --- a/apps/meteor/client/views/outlookCalendar/hooks/useOutlookCalendarList.ts +++ b/apps/meteor/client/views/outlookCalendar/hooks/useOutlookCalendarList.ts @@ -11,9 +11,13 @@ export const useOutlookCalendarListForToday = () => { export const useOutlookCalendarList = (date: Date) => { const calendarData = useEndpoint('GET', '/v1/calendar-events.list'); - return useQuery(['outlook', 'calendar', 'list'], async () => { - const { data } = await calendarData({ date: date.toISOString() }); - return data; + return useQuery({ + queryKey: ['outlook', 'calendar', 'list'], + + queryFn: async () => { + const { data } = await calendarData({ date: date.toISOString() }); + return data; + }, }); }; @@ -29,7 +33,9 @@ export const useMutationOutlookCalendarSync = () => { mutationFn: async () => { await syncOutlookEvents(); - await queryClient.invalidateQueries(['outlook', 'calendar', 'list']); + await queryClient.invalidateQueries({ + queryKey: ['outlook', 'calendar', 'list'], + }); await checkOutlookCredentials.mutateAsync(); }, diff --git a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts index 4cfbbe0aed77..520743551e7f 100644 --- a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts +++ b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts @@ -12,18 +12,16 @@ export const usePutChatOnHoldMutation = ( const queryClient = useQueryClient(); - return useMutation( - async (rid) => { + return useMutation({ + mutationFn: async (rid) => { await putChatOnHold({ roomId: rid }); }, - { - ...options, - onSuccess: async (data, rid, context) => { - await queryClient.invalidateQueries(['current-chats']); - await queryClient.invalidateQueries(['rooms', rid]); - await queryClient.invalidateQueries(subscriptionsQueryKeys.subscription(rid)); - return options?.onSuccess?.(data, rid, context); - }, + ...options, + onSuccess: async (data, rid, context) => { + await queryClient.invalidateQueries({ queryKey: ['current-chats'] }); + await queryClient.invalidateQueries({ queryKey: ['rooms', rid] }); + await queryClient.invalidateQueries({ queryKey: subscriptionsQueryKeys.subscription(rid) }); + return options?.onSuccess?.(data, rid, context); }, - ); + }); }; diff --git a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts index c44afc8a2d08..5811a989bbc0 100644 --- a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts +++ b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts @@ -12,19 +12,17 @@ export const useReturnChatToQueueMutation = ( const queryClient = useQueryClient(); - return useMutation( - async (rid) => { + return useMutation({ + mutationFn: async (rid) => { await returnChatToQueue(rid); }, - { - ...options, - onSuccess: async (data, rid, context) => { - await queryClient.invalidateQueries(['current-chats']); - queryClient.removeQueries(['rooms', rid]); - queryClient.removeQueries(['/v1/rooms.info', rid]); - queryClient.removeQueries(subscriptionsQueryKeys.subscription(rid)); - return options?.onSuccess?.(data, rid, context); - }, + ...options, + onSuccess: async (data, rid, context) => { + await queryClient.invalidateQueries({ queryKey: ['current-chats'] }); + queryClient.removeQueries({ queryKey: ['rooms', rid] }); + queryClient.removeQueries({ queryKey: ['/v1/rooms.info', rid] }); + queryClient.removeQueries({ queryKey: subscriptionsQueryKeys.subscription(rid) }); + return options?.onSuccess?.(data, rid, context); }, - ); + }); }; diff --git a/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx b/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx index 9dd875c3bce7..ceb6041c76d3 100644 --- a/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx +++ b/apps/meteor/client/views/room/Header/ParentRoomWithEndpointData.tsx @@ -10,9 +10,9 @@ type ParentRoomWithEndpointDataProps = { }; const ParentRoomWithEndpointData = ({ rid }: ParentRoomWithEndpointDataProps): ReactElement | null => { - const { data, isLoading, isError } = useRoomInfoEndpoint(rid); + const { data, isPending, isError } = useRoomInfoEndpoint(rid); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/room/Header/ParentTeam.tsx b/apps/meteor/client/views/room/Header/ParentTeam.tsx index 498b3fe1d8c0..4084cc12a190 100644 --- a/apps/meteor/client/views/room/Header/ParentTeam.tsx +++ b/apps/meteor/client/views/room/Header/ParentTeam.tsx @@ -1,7 +1,7 @@ import type { IRoom } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; import { useUserId, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import { HeaderTag, HeaderTagIcon, HeaderTagSkeleton } from '../../../components/Header'; @@ -28,12 +28,17 @@ const ParentTeam = ({ room }: { room: IRoom }): ReactElement | null => { data: teamInfoData, isLoading: teamInfoLoading, isError: teamInfoError, - } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { - keepPreviousData: true, - retry: (_, error) => (error as APIErrorResult)?.error === 'unauthorized' && false, + } = useQuery({ + queryKey: ['teamId', teamId], + queryFn: async () => teamsInfoEndpoint({ teamId }), + placeholderData: keepPreviousData, + retry: (_, error: APIErrorResult) => error?.error === 'unauthorized' && false, }); - const { data: userTeams, isLoading: userTeamsLoading } = useQuery(['userId', userId], async () => userTeamsListEndpoint({ userId })); + const { data: userTeams, isLoading: userTeamsLoading } = useQuery({ + queryKey: ['userId', userId], + queryFn: async () => userTeamsListEndpoint({ userId }), + }); const userBelongsToTeam = userTeams?.teams?.find((team) => team._id === teamId) || false; const isTeamPublic = teamInfoData?.teamInfo.type === TEAM_TYPE.PUBLIC; diff --git a/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts b/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts index 4cfbbe0aed77..520743551e7f 100644 --- a/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts +++ b/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/usePutChatOnHoldMutation.ts @@ -12,18 +12,16 @@ export const usePutChatOnHoldMutation = ( const queryClient = useQueryClient(); - return useMutation( - async (rid) => { + return useMutation({ + mutationFn: async (rid) => { await putChatOnHold({ roomId: rid }); }, - { - ...options, - onSuccess: async (data, rid, context) => { - await queryClient.invalidateQueries(['current-chats']); - await queryClient.invalidateQueries(['rooms', rid]); - await queryClient.invalidateQueries(subscriptionsQueryKeys.subscription(rid)); - return options?.onSuccess?.(data, rid, context); - }, + ...options, + onSuccess: async (data, rid, context) => { + await queryClient.invalidateQueries({ queryKey: ['current-chats'] }); + await queryClient.invalidateQueries({ queryKey: ['rooms', rid] }); + await queryClient.invalidateQueries({ queryKey: subscriptionsQueryKeys.subscription(rid) }); + return options?.onSuccess?.(data, rid, context); }, - ); + }); }; diff --git a/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts b/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts index c44afc8a2d08..5811a989bbc0 100644 --- a/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts +++ b/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useReturnChatToQueueMutation.ts @@ -12,19 +12,17 @@ export const useReturnChatToQueueMutation = ( const queryClient = useQueryClient(); - return useMutation( - async (rid) => { + return useMutation({ + mutationFn: async (rid) => { await returnChatToQueue(rid); }, - { - ...options, - onSuccess: async (data, rid, context) => { - await queryClient.invalidateQueries(['current-chats']); - queryClient.removeQueries(['rooms', rid]); - queryClient.removeQueries(['/v1/rooms.info', rid]); - queryClient.removeQueries(subscriptionsQueryKeys.subscription(rid)); - return options?.onSuccess?.(data, rid, context); - }, + ...options, + onSuccess: async (data, rid, context) => { + await queryClient.invalidateQueries({ queryKey: ['current-chats'] }); + queryClient.removeQueries({ queryKey: ['rooms', rid] }); + queryClient.removeQueries({ queryKey: ['/v1/rooms.info', rid] }); + queryClient.removeQueries({ queryKey: subscriptionsQueryKeys.subscription(rid) }); + return options?.onSuccess?.(data, rid, context); }, - ); + }); }; diff --git a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx index 68b53936e02e..0f8cb89bc4b7 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentRoomWithEndpointData.tsx @@ -9,9 +9,9 @@ type ParentRoomWithEndpointDataProps = { }; const ParentRoomWithEndpointData = ({ rid }: ParentRoomWithEndpointDataProps) => { - const { data, isLoading, isError } = useRoomInfoEndpoint(rid); + const { data, isPending, isError } = useRoomInfoEndpoint(rid); - if (isLoading) { + if (isPending) { return ; } diff --git a/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx b/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx index a63b7f17ad59..475054c07a9b 100644 --- a/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx +++ b/apps/meteor/client/views/room/HeaderV2/ParentTeam.tsx @@ -1,7 +1,7 @@ import type { IRoom } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; import { useUserId, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { HeaderTag, HeaderTagIcon, HeaderTagSkeleton } from '../../../components/Header'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; @@ -31,12 +31,17 @@ const ParentTeam = ({ room }: ParentTeamProps) => { data: teamInfoData, isLoading: teamInfoLoading, isError: teamInfoError, - } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { - keepPreviousData: true, - retry: (_, error) => (error as APIErrorResult)?.error === 'unauthorized' && false, + } = useQuery({ + queryKey: ['teamId', teamId], + queryFn: async () => teamsInfoEndpoint({ teamId }), + placeholderData: keepPreviousData, + retry: (_, error: APIErrorResult) => error?.error === 'unauthorized' && false, }); - const { data: userTeams, isLoading: userTeamsLoading } = useQuery(['userId', userId], async () => userTeamsListEndpoint({ userId })); + const { data: userTeams, isLoading: userTeamsLoading } = useQuery({ + queryKey: ['userId', userId], + queryFn: async () => userTeamsListEndpoint({ userId }), + }); const userBelongsToTeam = userTeams?.teams?.find((team) => team._id === teamId) || false; const isTeamPublic = teamInfoData?.teamInfo.type === TEAM_TYPE.PUBLIC; diff --git a/apps/meteor/client/views/room/MessageList/hooks/useParentMessage.ts b/apps/meteor/client/views/room/MessageList/hooks/useParentMessage.ts index df4a5b122e06..519093523e13 100644 --- a/apps/meteor/client/views/room/MessageList/hooks/useParentMessage.ts +++ b/apps/meteor/client/views/room/MessageList/hooks/useParentMessage.ts @@ -5,4 +5,7 @@ import { useQuery } from '@tanstack/react-query'; import { findParentMessage } from '../../../../../app/ui-message/client/findParentMessage'; export const useParentMessage = (mid: IMessage['_id']): UseQueryResult => - useQuery(['parent-message', { mid }], async () => findParentMessage(mid)); + useQuery({ + queryKey: ['parent-message', { mid }], + queryFn: async () => findParentMessage(mid), + }); diff --git a/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx b/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx index fd4f6d50bbde..9b9772d8c768 100644 --- a/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx +++ b/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx @@ -4,7 +4,7 @@ import { FeaturePreviewOff, FeaturePreviewOn } from '@rocket.chat/ui-client'; import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; -import { lazy, Suspense } from 'react'; +import { lazy, Suspense, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import RoomSkeleton from './RoomSkeleton'; @@ -37,25 +37,24 @@ const RoomOpenerEmbedded = ({ type, reference }: RoomOpenerProps): ReactElement const getSubscription = useEndpoint('GET', '/v1/subscriptions.getOne'); const rid = data?.rid; - useQuery( - ['subscriptions', rid], - () => { + const { data: subscription } = useQuery({ + queryKey: ['subscriptions', rid] as const, + queryFn: () => { if (!rid) { throw new Error('Room not found'); } return getSubscription({ roomId: rid }); }, - { - enabled: !!rid, - suspense: true, - onSuccess({ subscription }) { - if (!subscription) { - throw new Error('Room not found'); - } - CachedChatSubscription.upsertSubscription(subscription as unknown as ISubscription); - }, - }, - ); + enabled: !!rid, + }); + + useEffect(() => { + if (!subscription) { + return; + } + + CachedChatSubscription.upsertSubscription(subscription as unknown as ISubscription); + }, [subscription]); const { t } = useTranslation(); diff --git a/apps/meteor/client/views/room/ShareLocation/ShareLocationModal.tsx b/apps/meteor/client/views/room/ShareLocation/ShareLocationModal.tsx index 4b8a5a5f42d7..90b0ee999426 100644 --- a/apps/meteor/client/views/room/ShareLocation/ShareLocationModal.tsx +++ b/apps/meteor/client/views/room/ShareLocation/ShareLocationModal.tsx @@ -17,12 +17,19 @@ type ShareLocationModalProps = { const ShareLocationModal = ({ rid, tmid, onClose }: ShareLocationModalProps): ReactElement => { const t = useTranslation(); const dispatchToast = useToastMessageDispatch(); - const { data: permissionData, isLoading: permissionLoading } = useQuery(['geolocationPermission'], getGeolocationPermission); - const { data: positionData } = useQuery(['geolocationPosition', permissionData], async () => { - if (permissionLoading || permissionData === 'prompt' || permissionData === 'denied') { - return; - } - return getGeolocationPosition(); + const { data: permissionState, isLoading: permissionLoading } = useQuery({ + queryKey: ['geolocationPermission'], + queryFn: getGeolocationPermission, + }); + const { data: positionData } = useQuery({ + queryKey: ['geolocationPosition', permissionState], + + queryFn: async () => { + if (permissionLoading || permissionState === 'prompt' || permissionState === 'denied') { + return; + } + return getGeolocationPosition(); + }, }); const queryClient = useQueryClient(); @@ -61,7 +68,7 @@ const ShareLocationModal = ({ rid, tmid, onClose }: ShareLocationModalProps): Re } }; - if (permissionLoading || permissionData === 'prompt') { + if (permissionLoading || permissionState === 'prompt') { return ( {t('The_necessary_browser_permissions_for_location_sharing_are_not_granted')} diff --git a/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx b/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx index 56bd0f0466cd..1ee6ddb99a9a 100644 --- a/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx +++ b/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx @@ -39,7 +39,7 @@ const RoomSidepanelWithData = ({ parentRid, openedRoom }: { parentRid: string; o return null; } - if (roomInfo.isLoading || (roomInfo.isSuccess && result.isLoading)) { + if (roomInfo.isLoading || (roomInfo.isSuccess && result.isPending)) { return ; } diff --git a/apps/meteor/client/views/room/Sidepanel/hooks/useTeamslistChildren.ts b/apps/meteor/client/views/room/Sidepanel/hooks/useTeamslistChildren.ts index f18753ed15c1..e6ab0a90b4a6 100644 --- a/apps/meteor/client/views/room/Sidepanel/hooks/useTeamslistChildren.ts +++ b/apps/meteor/client/views/room/Sidepanel/hooks/useTeamslistChildren.ts @@ -1,5 +1,5 @@ import type { ISubscription } from '@rocket.chat/core-typings'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { Mongo } from 'meteor/mongo'; import { useEffect, useMemo } from 'react'; @@ -41,16 +41,16 @@ export const useTeamsListChildrenUpdate = ( queryFn: () => Subscriptions.find(query, options).fetch(), enabled: sidepanelItems !== null && teamId !== null, refetchInterval: 5 * 60 * 1000, - keepPreviousData: true, + placeholderData: keepPreviousData, }); const { refetch } = result; useEffect(() => { const liveQueryHandle = Subscriptions.find(query).observe({ - added: () => queueMicrotask(() => refetch({ exact: false })), - changed: () => queueMicrotask(() => refetch({ exact: false })), - removed: () => queueMicrotask(() => refetch({ exact: false })), + added: () => queueMicrotask(() => refetch()), + changed: () => queueMicrotask(() => refetch()), + removed: () => queueMicrotask(() => refetch()), }); return () => { diff --git a/apps/meteor/client/views/room/body/RoomForeword/RoomForewordUsernameListItem.tsx b/apps/meteor/client/views/room/body/RoomForeword/RoomForewordUsernameListItem.tsx index cad260a1a990..48c0cd36a703 100644 --- a/apps/meteor/client/views/room/body/RoomForeword/RoomForewordUsernameListItem.tsx +++ b/apps/meteor/client/views/room/body/RoomForeword/RoomForewordUsernameListItem.tsx @@ -11,13 +11,13 @@ type RoomForewordUsernameListItemProps = { }; const RoomForewordUsernameListItem = ({ username, href, useRealName }: RoomForewordUsernameListItemProps) => { - const { data, isLoading, isError } = useUserInfoQuery({ username }); + const { data, isLoading, isError, isSuccess } = useUserInfoQuery({ username }); return ( } data-username={username} large href={href}> {isLoading && } - {!isLoading && isError && username} - {!isLoading && !isError && getUserDisplayName(data?.user?.name, username, useRealName)} + {isError && username} + {isSuccess && getUserDisplayName(data?.user?.name, username, useRealName)} ); }; diff --git a/apps/meteor/client/views/room/body/hooks/useGoToHomeOnRemoved.ts b/apps/meteor/client/views/room/body/hooks/useGoToHomeOnRemoved.ts index 5aa8eae0df07..87aba99721d3 100644 --- a/apps/meteor/client/views/room/body/hooks/useGoToHomeOnRemoved.ts +++ b/apps/meteor/client/views/room/body/hooks/useGoToHomeOnRemoved.ts @@ -21,7 +21,9 @@ export function useGoToHomeOnRemoved(room: IRoom, userId?: string): void { return subscribeToNotifyUser(`${userId}/subscriptions-changed`, (event, subscription) => { if (event === 'removed' && subscription.rid === room._id) { - queryClient.invalidateQueries(['rooms', room._id]); + queryClient.invalidateQueries({ + queryKey: ['rooms', room._id], + }); if (isOmnichannelRoom({ t: room.t })) { navigateHome(); diff --git a/apps/meteor/client/views/room/composer/ComposerAnonymous.tsx b/apps/meteor/client/views/room/composer/ComposerAnonymous.tsx index 793425a5983a..194fa373a0b4 100644 --- a/apps/meteor/client/views/room/composer/ComposerAnonymous.tsx +++ b/apps/meteor/client/views/room/composer/ComposerAnonymous.tsx @@ -19,20 +19,19 @@ const ComposerAnonymous = (): ReactElement => { const anonymousUser = useMethod('registerUser'); const setForceLogin = useSessionDispatch('forceLogin'); - const registerAnonymous = useMutation( - async (...params: Parameters) => { + const registerAnonymous = useMutation({ + mutationFn: async (...params: Parameters) => { const result = await anonymousUser(...params); if (typeof result !== 'string' && result.token) { await loginWithToken(result.token); } return result; }, - { - onError: (error) => { - dispatch({ type: 'error', message: error }); - }, + + onError: (error) => { + dispatch({ type: 'error', message: error }); }, - ); + }); const joinAnonymous = () => { registerAnonymous.mutate({ email: null }); diff --git a/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelCallout.tsx b/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelCallout.tsx index d9291b9d6545..b1ce6cc244d3 100644 --- a/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelCallout.tsx +++ b/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelCallout.tsx @@ -30,7 +30,7 @@ const ComposerOmnichannelCallout = () => { } = room; const getContactById = useEndpoint('GET', '/v1/omnichannel/contacts.get'); - const { data } = useQuery(['getContactById', contactId], () => getContactById({ contactId })); + const { data } = useQuery({ queryKey: ['getContactById', contactId], queryFn: () => getContactById({ contactId }) }); const association = { visitorId, source }; const currentChannel = data?.contact?.channels?.find((channel) => isSameChannel(channel.visitor, association)); diff --git a/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelInquiry.tsx b/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelInquiry.tsx index c145b38ac1f3..785f274183ab 100644 --- a/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelInquiry.tsx +++ b/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelInquiry.tsx @@ -14,11 +14,14 @@ export const ComposerOmnichannelInquiry = (): ReactElement => { const agentAvailable = useOmnichannelAgentAvailable(); const room = useOmnichannelRoom(); const getInquire = useEndpoint('GET', `/v1/livechat/inquiries.getOne`); - const result = useQuery(['inquire', room._id], () => - getInquire({ - roomId: room._id, - }), - ); + const result = useQuery({ + queryKey: ['inquire', room._id], + + queryFn: () => + getInquire({ + roomId: room._id, + }), + }); const takeInquiry = useMethod('livechat:takeInquiry'); @@ -47,11 +50,11 @@ export const ComposerOmnichannelInquiry = (): ReactElement => { }, [agentAvailable, t, user?.status]); return ( - + {t('you_are_in_preview_mode_of_incoming_livechat')} {t('Take_it')} diff --git a/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelOnHold.tsx b/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelOnHold.tsx index 8b5bf245f327..26accba16401 100644 --- a/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelOnHold.tsx +++ b/apps/meteor/client/views/room/composer/ComposerOmnichannel/ComposerOmnichannelOnHold.tsx @@ -16,7 +16,7 @@ export const ComposerOmnichannelOnHold = (): ReactElement => { {t('chat_on_hold_due_to_inactivity')} resumeChatOnHoldMutation.mutate(room._id)} > {t('Resume')} diff --git a/apps/meteor/client/views/room/composer/ComposerOmnichannel/hooks/useResumeChatOnHoldMutation.ts b/apps/meteor/client/views/room/composer/ComposerOmnichannel/hooks/useResumeChatOnHoldMutation.ts index e6bf592b1561..261417069ce8 100644 --- a/apps/meteor/client/views/room/composer/ComposerOmnichannel/hooks/useResumeChatOnHoldMutation.ts +++ b/apps/meteor/client/views/room/composer/ComposerOmnichannel/hooks/useResumeChatOnHoldMutation.ts @@ -14,21 +14,23 @@ export const useResumeChatOnHoldMutation = ( const queryClient = useQueryClient(); - return useMutation( - async (roomId) => { + return useMutation({ + mutationFn: async (roomId) => { await resumeChatOnHold({ roomId }); }, - { - ...options, - onSuccess: async (data, rid, context) => { - await queryClient.invalidateQueries(['current-chats']); - await queryClient.invalidateQueries(['rooms', rid]); - await queryClient.invalidateQueries(subscriptionsQueryKeys.subscription(rid)); - return options?.onSuccess?.(data, rid, context); - }, - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); - }, + ...options, + onSuccess: async (data, rid, context) => { + await queryClient.invalidateQueries({ + queryKey: ['current-chats'], + }); + await queryClient.invalidateQueries({ + queryKey: ['rooms', rid], + }); + await queryClient.invalidateQueries({ queryKey: subscriptionsQueryKeys.subscription(rid) }); + return options?.onSuccess?.(data, rid, context); }, - ); + onError: (error) => { + dispatchToastMessage({ type: 'error', message: error }); + }, + }); }; diff --git a/apps/meteor/client/views/room/composer/ComposerReadOnly.tsx b/apps/meteor/client/views/room/composer/ComposerReadOnly.tsx index 7fec32e28922..0a2f18d25d24 100644 --- a/apps/meteor/client/views/room/composer/ComposerReadOnly.tsx +++ b/apps/meteor/client/views/room/composer/ComposerReadOnly.tsx @@ -14,7 +14,9 @@ const ComposerReadOnly = (): ReactElement => { const isSubscribed = useUserIsSubscribed(); const joinChannel = useEndpoint('POST', '/v1/channels.join'); - const join = useMutation(() => joinChannel({ roomId: room._id }), { + const join = useMutation({ + mutationFn: () => joinChannel({ roomId: room._id }), + onError: (error: unknown) => { dispatchToastMessage({ type: 'error', message: error }); }, @@ -24,7 +26,7 @@ const ComposerReadOnly = (): ReactElement => { {t('room_is_read_only')} {!isSubscribed && ( - )} diff --git a/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopupQueries.ts b/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopupQueries.ts index d2ee61ffeaee..a71c7f59ac1c 100644 --- a/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopupQueries.ts +++ b/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopupQueries.ts @@ -1,5 +1,5 @@ import type { QueriesResults } from '@tanstack/react-query'; -import { useQueries } from '@tanstack/react-query'; +import { keepPreviousData, useQueries } from '@tanstack/react-query'; import { useEffect, useState } from 'react'; import { useEnablePopupPreview } from './useEnablePopupPreview'; @@ -26,7 +26,7 @@ export const useComposerBoxPopupQueries = popup?.getItemsFromLocal && popup.getItemsFromLocal(filter), onSuccess: (args: T[]) => { @@ -37,7 +37,7 @@ export const useComposerBoxPopupQueries = popup?.getItemsFromServer && popup.getItemsFromServer(filter), enabled: counter > 0, diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx index 9ff5765b9fd3..afc36b4f746f 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx @@ -284,7 +284,9 @@ const MessageBox = ({ const format = useFormatDateAndTime(); - const joinMutation = useMutation(async () => onJoin?.()); + const joinMutation = useMutation({ + mutationFn: async () => onJoin?.(), + }); const handlePaste: ClipboardEventHandler = useMutableCallback((event) => { const { clipboardData } = event; @@ -433,7 +435,7 @@ const MessageBox = ({ {!canSend && ( - + {t('Join')} )} diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx index 09744559a50b..c2f585f3a4b5 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx @@ -196,7 +196,9 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => }), }); - await query.invalidateQueries(['/v1/rooms.info', room._id]); + await query.invalidateQueries({ + queryKey: ['/v1/rooms.info', room._id], + }); dispatchToastMessage({ type: 'success', message: t('Room_updated_successfully') }); onClickClose(); } catch (error) { diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomPermissions.ts b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomPermissions.ts index 7f9043bfb824..1f0d11046eed 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomPermissions.ts +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomPermissions.ts @@ -1,6 +1,6 @@ import type { IRoom, IRoomWithRetentionPolicy } from '@rocket.chat/core-typings'; import { usePermission, useAtLeastOnePermission, useRole, useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { useMemo } from 'react'; import { E2EEState } from '../../../../../../app/e2e/client/E2EEState'; @@ -20,8 +20,10 @@ export const useEditRoomPermissions = (room: IRoom | IRoomWithRetentionPolicy) = const teamsInfoEndpoint = useEndpoint('GET', '/v1/teams.info'); const teamId = room.teamId || ''; - const { data: teamInfoData } = useQuery(['teamId', teamId], async () => teamsInfoEndpoint({ teamId }), { - keepPreviousData: true, + const { data: teamInfoData } = useQuery({ + queryKey: ['teamId', teamId], + queryFn: async () => teamsInfoEndpoint({ teamId }), + placeholderData: keepPreviousData, retry: false, enabled: room.teamId !== '', }); diff --git a/apps/meteor/client/views/room/contextualBar/MentionsTab.tsx b/apps/meteor/client/views/room/contextualBar/MentionsTab.tsx index f11c4109bd9f..2c0880d39907 100644 --- a/apps/meteor/client/views/room/contextualBar/MentionsTab.tsx +++ b/apps/meteor/client/views/room/contextualBar/MentionsTab.tsx @@ -13,19 +13,23 @@ const MentionsTab = (): ReactElement => { const room = useRoom(); - const mentionedMessagesQueryResult = useQuery(['rooms', room._id, 'mentioned-messages'] as const, async () => { - const messages: IMessage[] = []; - - for ( - let offset = 0, result = await getMentionedMessages({ roomId: room._id, offset: 0 }); - result.count > 0; - // eslint-disable-next-line no-await-in-loop - offset += result.count, result = await getMentionedMessages({ roomId: room._id, offset }) - ) { - messages.push(...result.messages.map(mapMessageFromApi)); - } - - return messages; + const mentionedMessagesQueryResult = useQuery({ + queryKey: ['rooms', room._id, 'mentioned-messages'] as const, + + queryFn: async () => { + const messages: IMessage[] = []; + + for ( + let offset = 0, result = await getMentionedMessages({ roomId: room._id, offset: 0 }); + result.count > 0; + // eslint-disable-next-line no-await-in-loop + offset += result.count, result = await getMentionedMessages({ roomId: room._id, offset }) + ) { + messages.push(...result.messages.map(mapMessageFromApi)); + } + + return messages; + }, }); const { t } = useTranslation(); diff --git a/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchProviderQuery.ts b/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchProviderQuery.ts index b68d20341360..3d7ca1c53371 100644 --- a/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchProviderQuery.ts +++ b/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchProviderQuery.ts @@ -3,12 +3,16 @@ import { useQuery } from '@tanstack/react-query'; export const useMessageSearchProviderQuery = () => { const getSearchProvider = useMethod('rocketchatSearch.getProvider'); - return useQuery(['search', 'provider'] as const, async () => { - const provider = await getSearchProvider(); - if (provider === undefined) { - throw new Error('Search provider not found'); - } + return useQuery({ + queryKey: ['search', 'provider'] as const, - return provider; + queryFn: async () => { + const provider = await getSearchProvider(); + if (provider === undefined) { + throw new Error('Search provider not found'); + } + + return provider; + }, }); }; diff --git a/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchQuery.ts b/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchQuery.ts index 0b5047542cd2..7402c5ab7576 100644 --- a/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchQuery.ts +++ b/apps/meteor/client/views/room/contextualBar/MessageSearchTab/hooks/useMessageSearchQuery.ts @@ -1,5 +1,5 @@ -import { useMethod, useToastMessageDispatch, useTranslation, useUserId } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { useMethod, useTranslation, useUserId } from '@rocket.chat/ui-contexts'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { useRoom } from '../../../contexts/RoomContext'; @@ -16,23 +16,18 @@ export const useMessageSearchQuery = ({ const room = useRoom(); const t = useTranslation(); - const dispatchToastMessage = useToastMessageDispatch(); const searchMessages = useMethod('rocketchatSearch.search'); - return useQuery( - ['rooms', room._id, 'message-search', { uid, rid: room._id, searchText, limit, globalSearch }] as const, - async () => { + return useQuery({ + queryKey: ['rooms', room._id, 'message-search', { uid, rid: room._id, searchText, limit, globalSearch }] as const, + + queryFn: async () => { const result = await searchMessages(searchText, { uid, rid: room._id }, { limit, searchAll: globalSearch }); return result.message?.docs ?? []; }, - { - keepPreviousData: true, - onError: () => { - dispatchToastMessage({ - type: 'error', - message: t('Search_message_search_failed'), - }); - }, + placeholderData: keepPreviousData, + meta: { + errorToastMessage: t('Search_message_search_failed'), }, - ); + }); }; diff --git a/apps/meteor/client/views/room/contextualBar/PinnedMessagesTab.tsx b/apps/meteor/client/views/room/contextualBar/PinnedMessagesTab.tsx index 475ebf1572f5..e1dab3e0c747 100644 --- a/apps/meteor/client/views/room/contextualBar/PinnedMessagesTab.tsx +++ b/apps/meteor/client/views/room/contextualBar/PinnedMessagesTab.tsx @@ -14,19 +14,23 @@ const PinnedMessagesTab = (): ReactElement => { const room = useRoom(); - const pinnedMessagesQueryResult = useQuery(['rooms', room._id, 'pinned-messages'] as const, async () => { - const messages: IMessage[] = []; - - for ( - let offset = 0, result = await getPinnedMessages({ roomId: room._id, offset: 0 }); - result.count > 0; - // eslint-disable-next-line no-await-in-loop - offset += result.count, result = await getPinnedMessages({ roomId: room._id, offset }) - ) { - messages.push(...result.messages.map(mapMessageFromApi)); - } - - return Promise.all(messages.map(onClientMessageReceived)); + const pinnedMessagesQueryResult = useQuery({ + queryKey: ['rooms', room._id, 'pinned-messages'] as const, + + queryFn: async () => { + const messages: IMessage[] = []; + + for ( + let offset = 0, result = await getPinnedMessages({ roomId: room._id, offset: 0 }); + result.count > 0; + // eslint-disable-next-line no-await-in-loop + offset += result.count, result = await getPinnedMessages({ roomId: room._id, offset }) + ) { + messages.push(...result.messages.map(mapMessageFromApi)); + } + + return Promise.all(messages.map(onClientMessageReceived)); + }, }); const { t } = useTranslation(); diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx index 85897fc9ca1a..2bb65577ea38 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddMatrixUsers/useAddMatrixUsers.tsx @@ -15,26 +15,28 @@ export const useAddMatrixUsers = () => { const handleClose = useMutableCallback(() => setModal(null)); const dispatchVerifyEndpoint = useEndpoint('GET', '/v1/federation/matrixIds.verify'); - return useMutation(async ({ users, handleSave }: useAddMatrixUsersProps) => { - try { - let matrixIdVerificationMap = new Map(); - const matrixIds = users.filter((user) => user.startsWith('@')); - if (matrixIds.length > 0) { - const matrixIdsVerificationResponse = await dispatchVerifyEndpoint({ matrixIds }); - const { results: matrixIdsVerificationResults } = matrixIdsVerificationResponse; - matrixIdVerificationMap = new Map(Object.entries(matrixIdsVerificationResults)); - } + return useMutation({ + mutationFn: async ({ users, handleSave }: useAddMatrixUsersProps) => { + try { + let matrixIdVerificationMap = new Map(); + const matrixIds = users.filter((user) => user.startsWith('@')); + if (matrixIds.length > 0) { + const matrixIdsVerificationResponse = await dispatchVerifyEndpoint({ matrixIds }); + const { results: matrixIdsVerificationResults } = matrixIdsVerificationResponse; + matrixIdVerificationMap = new Map(Object.entries(matrixIdsVerificationResults)); + } - setModal( - } - />, - ); - } catch (error) { - dispatchToastMessage({ type: 'error', message: error as Error }); - } + setModal( + } + />, + ); + } catch (error) { + dispatchToastMessage({ type: 'error', message: error as Error }); + } + }, }); }; diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx index c06c214e8e8d..52c4f5deed16 100644 --- a/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx +++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/AddUsers/AddUsers.tsx @@ -87,7 +87,7 @@ const AddUsers = ({ rid, onClickBack, reload }: AddUsersProps): ReactElement => {isRoomFederated(room) ? ( - diff --git a/apps/meteor/client/views/room/modals/ReadReceiptsModal/ReadReceiptsModal.tsx b/apps/meteor/client/views/room/modals/ReadReceiptsModal/ReadReceiptsModal.tsx index 9526879135e6..fc3b60788bfd 100644 --- a/apps/meteor/client/views/room/modals/ReadReceiptsModal/ReadReceiptsModal.tsx +++ b/apps/meteor/client/views/room/modals/ReadReceiptsModal/ReadReceiptsModal.tsx @@ -1,4 +1,4 @@ -import type { IMessage, ReadReceipt } from '@rocket.chat/core-typings'; +import type { IMessage } from '@rocket.chat/core-typings'; import { useMethod, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; @@ -20,7 +20,10 @@ const ReadReceiptsModal = ({ messageId, onClose }: ReadReceiptsModalProps): Reac const getReadReceipts = useMethod('getReadReceipts'); - const readReceiptsResult = useQuery(['read-receipts', messageId], () => getReadReceipts({ messageId })); + const readReceiptsResult = useQuery({ + queryKey: ['read-receipts', messageId], + queryFn: () => getReadReceipts({ messageId }), + }); useEffect(() => { if (readReceiptsResult.isError) { @@ -33,12 +36,12 @@ const ReadReceiptsModal = ({ messageId, onClose }: ReadReceiptsModalProps): Reac return ; } - const readReceipts = readReceiptsResult.data; + const readReceipts = readReceiptsResult?.data; return ( - {readReceipts.length < 1 && t('No_results_found')} - {readReceipts.length > 0 && ( + {readReceipts && readReceipts.length < 1 && t('No_results_found')} + {readReceipts && readReceipts.length > 0 && (
{readReceipts.map((receipt) => ( diff --git a/apps/meteor/client/views/room/providers/hooks/useRoomQuery.ts b/apps/meteor/client/views/room/providers/hooks/useRoomQuery.ts index b808ff6da00c..63e60e43e8ac 100644 --- a/apps/meteor/client/views/room/providers/hooks/useRoomQuery.ts +++ b/apps/meteor/client/views/room/providers/hooks/useRoomQuery.ts @@ -12,7 +12,9 @@ export function useRoomQuery( ): UseQueryResult { const queryKey = ['rooms', rid] as const; - const queryResult = useQuery(queryKey, async (): Promise => Rooms.findOne({ _id: rid }, { reactive: false }) ?? null, { + const queryResult = useQuery({ + queryKey, + queryFn: async (): Promise => Rooms.findOne({ _id: rid }, { reactive: false }) ?? null, staleTime: Infinity, ...options, }); @@ -21,9 +23,9 @@ export function useRoomQuery( useEffect(() => { const liveQueryHandle = Rooms.find({ _id: rid }).observe({ - added: () => queueMicrotask(() => refetch({ exact: false })), - changed: () => queueMicrotask(() => refetch({ exact: false })), - removed: () => queueMicrotask(() => refetch({ exact: false })), + added: () => queueMicrotask(() => refetch()), + changed: () => queueMicrotask(() => refetch()), + removed: () => queueMicrotask(() => refetch()), }); return () => { diff --git a/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx b/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx index 53a3e3a2cf98..03765f6ef339 100644 --- a/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx +++ b/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx @@ -14,12 +14,11 @@ import { useMethod, useAccountsCustomFields, } from '@rocket.chat/ui-contexts'; -import { useQuery, useMutation } from '@tanstack/react-query'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useEffect } from 'react'; import { useForm } from 'react-hook-form'; import MarkdownText from '../../../components/MarkdownText'; -import { queryClient } from '../../../lib/queryClient'; type RegisterUsernamePayload = { username: Exclude; @@ -43,7 +42,10 @@ const RegisterUsername = () => { const setUsername = useMethod('setUsername'); const saveCustomFields = useMethod('saveCustomFields'); const usernameSuggestion = useEndpoint('GET', '/v1/users.getUsernameSuggestion'); - const { data, isLoading } = useQuery(['suggestion'], async () => usernameSuggestion()); + const { data, isLoading } = useQuery({ + queryKey: ['suggestion'], + queryFn: async () => usernameSuggestion(), + }); const { register, @@ -63,6 +65,8 @@ const RegisterUsername = () => { } }); + const queryClient = useQueryClient(); + const registerUsernameMutation = useMutation({ mutationFn: async (data: RegisterUsernamePayload) => { const { username, ...customFields } = data; @@ -70,7 +74,7 @@ const RegisterUsername = () => { }, onSuccess: () => { dispatchToastMessage({ type: 'success', message: t('Username_has_been_updated') }); - queryClient.invalidateQueries(['users.info']); + queryClient.invalidateQueries({ queryKey: ['users.info'] }); }, onError: (error: any, { username }) => { if ([error.error, error.errorType].includes('error-blocked-username')) { diff --git a/apps/meteor/client/views/root/hooks/useClearUnreadAllMessagesMutation.ts b/apps/meteor/client/views/root/hooks/useClearUnreadAllMessagesMutation.ts index e9802db9d999..bccca6f5a304 100644 --- a/apps/meteor/client/views/root/hooks/useClearUnreadAllMessagesMutation.ts +++ b/apps/meteor/client/views/root/hooks/useClearUnreadAllMessagesMutation.ts @@ -7,29 +7,32 @@ import { Subscriptions } from '../../../../app/models/client'; export const useClearUnreadAllMessagesMutation = (options?: Omit, 'mutationFn'>) => { const readSubscription = useEndpoint('POST', '/v1/subscriptions.read'); - return useMutation(async () => { - const promises = Subscriptions.find( - { - open: true, - }, - { - fields: { - unread: 1, - alert: 1, - rid: 1, - t: 1, - name: 1, - ls: 1, + return useMutation({ + mutationFn: async () => { + const promises = Subscriptions.find( + { + open: true, }, - }, - ).map((subscription) => { - if (subscription.alert || subscription.unread > 0) { - return readSubscription({ rid: subscription.rid, readThreads: true }); - } + { + fields: { + unread: 1, + alert: 1, + rid: 1, + t: 1, + name: 1, + ls: 1, + }, + }, + ).map((subscription) => { + if (subscription.alert || subscription.unread > 0) { + return readSubscription({ rid: subscription.rid, readThreads: true }); + } - return Promise.resolve(); - }); + return Promise.resolve(); + }); - await Promise.all(promises); - }, options); + await Promise.all(promises); + }, + ...options, + }); }; diff --git a/apps/meteor/client/views/setupWizard/hooks/useParameters.ts b/apps/meteor/client/views/setupWizard/hooks/useParameters.ts index 68e737f184d7..f76ba633d74b 100644 --- a/apps/meteor/client/views/setupWizard/hooks/useParameters.ts +++ b/apps/meteor/client/views/setupWizard/hooks/useParameters.ts @@ -11,7 +11,9 @@ type SetupWizardParameters = { export const useParameters = (): Exclude, { data: undefined }> => { const getSetupWizardParameters = useMethod('getSetupWizardParameters'); - return useQuery(['setupWizard/parameters'], getSetupWizardParameters, { + return useQuery({ + queryKey: ['setupWizard/parameters'], + queryFn: getSetupWizardParameters, initialData: { settings: [], serverAlreadyRegistered: false, diff --git a/apps/meteor/client/views/setupWizard/providers/SetupWizardProvider.tsx b/apps/meteor/client/views/setupWizard/providers/SetupWizardProvider.tsx index 1b2d17b6f36b..de333dec3914 100644 --- a/apps/meteor/client/views/setupWizard/providers/SetupWizardProvider.tsx +++ b/apps/meteor/client/views/setupWizard/providers/SetupWizardProvider.tsx @@ -9,6 +9,7 @@ import { useEndpoint, useTranslation, } from '@rocket.chat/ui-contexts'; +import { useQueryClient } from '@tanstack/react-query'; import { Meteor } from 'meteor/meteor'; import type { ReactElement, ContextType } from 'react'; import { useCallback, useMemo, useState } from 'react'; @@ -16,7 +17,6 @@ import { useCallback, useMemo, useState } from 'react'; import { callbacks } from '../../../../lib/callbacks'; import { validateEmail } from '../../../../lib/emailValidator'; import { useInvalidateLicense } from '../../../hooks/useLicense'; -import { queryClient } from '../../../lib/queryClient'; import { SetupWizardContext } from '../contexts/SetupWizardContext'; import { useParameters } from '../hooks/useParameters'; import { useStepRouting } from '../hooks/useStepRouting'; @@ -152,11 +152,13 @@ const SetupWizardProvider = ({ children }: { children: ReactElement }): ReactEle [dispatchSettings], ); + const queryClient = useQueryClient(); + const registerServer: HandleRegisterServer = useMutableCallback(async ({ email, resend = false }): Promise => { try { const { intentData } = await createRegistrationIntent({ resend, email }); invalidateLicenseQuery(100); - queryClient.invalidateQueries(['getRegistrationStatus']); + queryClient.invalidateQueries({ queryKey: ['getRegistrationStatus'] }); setSetupWizardData((prevState) => ({ ...prevState, diff --git a/apps/meteor/client/views/setupWizard/steps/RegisterServerStep.tsx b/apps/meteor/client/views/setupWizard/steps/RegisterServerStep.tsx index 564ec5ae6206..5362b162ad3a 100644 --- a/apps/meteor/client/views/setupWizard/steps/RegisterServerStep.tsx +++ b/apps/meteor/client/views/setupWizard/steps/RegisterServerStep.tsx @@ -36,32 +36,36 @@ const RegisterServerStep = (): ReactElement => { const registerPreIntent = useEndpoint('POST', '/v1/cloud.registerPreIntent'); const getWorkspaceRegisterData = useMethod('cloud:getWorkspaceRegisterData'); - const { data: clientKey } = useQuery(['setupWizard/clientKey'], async () => getWorkspaceRegisterData(), { + const { data: clientKey } = useQuery({ + queryKey: ['setupWizard/clientKey'], + queryFn: async () => getWorkspaceRegisterData(), staleTime: Infinity, }); const { data: offline, - isLoading, + isPending, isError, - } = useQuery(['setupWizard/registerIntent'], async () => registerPreIntent(), { + } = useQuery({ + queryKey: ['setupWizard/registerIntent'], + queryFn: async () => registerPreIntent(), staleTime: Infinity, select: (data) => data.offline, }); - const { mutate } = useMutation( - ['setupWizard/confirmOfflineRegistration'], - async (token) => registerManually({ cloudBlob: token }), - { - onSuccess: () => { - invalidateLicenseQuery(100); - completeSetupWizard(); - }, - onError: () => { - dispatchToastMessage({ type: 'error', message: t('Cloud_register_error') }); - }, + const { mutate } = useMutation({ + mutationKey: ['setupWizard/confirmOfflineRegistration'], + mutationFn: async (token: string) => registerManually({ cloudBlob: token }), + + onSuccess: () => { + invalidateLicenseQuery(100); + completeSetupWizard(); }, - ); + + onError: () => { + dispatchToastMessage({ type: 'error', message: t('Cloud_register_error') }); + }, + }); const handleConfirmOffline: ComponentProps['onSubmit'] = async ({ token, agreement }) => { await saveAgreementData(agreement); @@ -88,7 +92,7 @@ const RegisterServerStep = (): ReactElement => { stepCount={maxSteps} onSubmit={handleRegister} currentStep={currentStep} - offline={isError || (!isLoading && offline)} + offline={isError || (!isPending && offline)} /> ); diff --git a/apps/meteor/client/views/teams/contextualBar/TeamAutocomplete/TeamAutocomplete.tsx b/apps/meteor/client/views/teams/contextualBar/TeamAutocomplete/TeamAutocomplete.tsx index 4a33c5955350..21fe53722032 100644 --- a/apps/meteor/client/views/teams/contextualBar/TeamAutocomplete/TeamAutocomplete.tsx +++ b/apps/meteor/client/views/teams/contextualBar/TeamAutocomplete/TeamAutocomplete.tsx @@ -11,7 +11,10 @@ const TeamAutocomplete = ({ value, onChange, ...props }: TeamAutocompleteProps) const [filter, setFilter] = useState(''); const teamsAutoCompleteEndpoint = useEndpoint('GET', '/v1/teams.autocomplete'); - const { data, isSuccess } = useQuery(['teamsAutoComplete', filter], async () => teamsAutoCompleteEndpoint({ name: filter })); + const { data, isSuccess } = useQuery({ + queryKey: ['teamsAutoComplete', filter], + queryFn: async () => teamsAutoCompleteEndpoint({ name: filter }), + }); const options = useMemo( () => diff --git a/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/RoomsAvailableForTeamsAutoComplete.tsx b/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/RoomsAvailableForTeamsAutoComplete.tsx index b4d2689c85e1..d9a15f61b09a 100644 --- a/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/RoomsAvailableForTeamsAutoComplete.tsx +++ b/apps/meteor/client/views/teams/contextualBar/channels/AddExistingModal/RoomsAvailableForTeamsAutoComplete.tsx @@ -2,7 +2,7 @@ import { AutoComplete, Box, Option, Chip } from '@rocket.chat/fuselage'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; import { RoomAvatar } from '@rocket.chat/ui-avatar'; import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { ComponentProps } from 'react'; import { memo, useMemo, useState } from 'react'; @@ -16,11 +16,11 @@ const RoomsAvailableForTeamsAutoComplete = ({ value, onChange, ...props }: Rooms const roomsAvailableForTeamsAutoCompleteEndpoint = useEndpoint('GET', '/v1/rooms.autocomplete.availableForTeams'); - const { data } = useQuery( - ['roomsAvailableForTeamsAutoComplete', debouncedFilter], - async () => roomsAvailableForTeamsAutoCompleteEndpoint({ name: debouncedFilter }), - { keepPreviousData: true }, - ); + const { data } = useQuery({ + queryKey: ['roomsAvailableForTeamsAutoComplete', debouncedFilter], + queryFn: async () => roomsAvailableForTeamsAutoCompleteEndpoint({ name: debouncedFilter }), + placeholderData: keepPreviousData, + }); const options = useMemo(() => { if (!data) { diff --git a/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamModalWithRooms.tsx b/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamModalWithRooms.tsx index fb9d48be2083..f73189d4d5db 100644 --- a/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamModalWithRooms.tsx +++ b/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamModalWithRooms.tsx @@ -16,7 +16,10 @@ type DeleteTeamModalWithRoomsProps = { const DeleteTeamModalWithRooms = ({ teamId, onConfirm, onCancel }: DeleteTeamModalWithRoomsProps): ReactElement => { const query = useMemo(() => ({ teamId }), [teamId]); const getTeamsListRooms = useEndpoint('GET', '/v1/teams.listRooms'); - const { data, isLoading } = useQuery(['getTeamsListRooms', query], async () => getTeamsListRooms(query)); + const { data, isLoading } = useQuery({ + queryKey: ['getTeamsListRooms', query], + queryFn: async () => getTeamsListRooms(query), + }); if (isLoading) { return ; diff --git a/apps/meteor/client/views/teams/contextualBar/info/LeaveTeam/LeaveTeamWithData.tsx b/apps/meteor/client/views/teams/contextualBar/info/LeaveTeam/LeaveTeamWithData.tsx index 7a5e0d0db584..69fd55e87d88 100644 --- a/apps/meteor/client/views/teams/contextualBar/info/LeaveTeam/LeaveTeamWithData.tsx +++ b/apps/meteor/client/views/teams/contextualBar/info/LeaveTeam/LeaveTeamWithData.tsx @@ -20,7 +20,10 @@ const LeaveTeamWithData = ({ teamId, onCancel, onConfirm }: LeaveTeamWithDataPro } const getRoomsOfUser = useEndpoint('GET', '/v1/teams.listRoomsOfUser'); - const { data, isLoading } = useQuery(['teams.listRoomsOfUser'], () => getRoomsOfUser({ teamId, userId })); + const { data, isLoading } = useQuery({ + queryKey: ['teams.listRoomsOfUser'], + queryFn: () => getRoomsOfUser({ teamId, userId }), + }); if (isLoading) { return ; diff --git a/apps/meteor/package.json b/apps/meteor/package.json index 6120cc43b351..b8281142848c 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -295,7 +295,7 @@ "@rocket.chat/web-ui-registration": "workspace:^", "@slack/bolt": "^4.1.0", "@slack/rtm-api": "^7.0.1", - "@tanstack/react-query": "^4.36.1", + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch", "@vector-im/matrix-bot-sdk": "0.7.1-element.6", "@xmldom/xmldom": "^0.8.10", "adm-zip": "0.5.16", diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index 86000b6b877f..a71c300b7e71 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -71,7 +71,7 @@ "@storybook/react": "^8.4.4", "@storybook/react-webpack5": "^8.4.4", "@storybook/theming": "^8.4.4", - "@tanstack/react-query": "^4.36.1", + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch", "@testing-library/react": "~16.0.1", "@testing-library/user-event": "~14.5.2", "@types/react": "~17.0.80", diff --git a/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/VideoConferenceBlock.tsx b/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/VideoConferenceBlock.tsx index c56121585318..64401e43b82c 100644 --- a/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/VideoConferenceBlock.tsx +++ b/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/VideoConferenceBlock.tsx @@ -97,7 +97,7 @@ const VideoConferenceBlock = ({ } }; - if (result.isLoading || result.isError) { + if (result.isPending || result.isError) { // TODO: error handling return ; } diff --git a/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfData.ts b/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfData.ts index cc3081db7af6..92c4b4be2a46 100644 --- a/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfData.ts +++ b/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfData.ts @@ -4,18 +4,17 @@ import { useQuery } from '@tanstack/react-query'; export const useVideoConfData = ({ callId }: { callId: string }) => { const getVideoConfInfo = useEndpoint('GET', '/v1/video-conference.info'); - return useQuery( - ['video-conference', callId], - () => getVideoConfInfo({ callId }), - { - staleTime: Infinity, - refetchOnMount: (query) => { - if (query.state.data?.endedAt) { - return false; - } + return useQuery({ + queryKey: ['video-conference', callId], + queryFn: () => getVideoConfInfo({ callId }), + staleTime: Infinity, - return 'always'; - }, + refetchOnMount: (query) => { + if (query.state.data?.endedAt) { + return false; + } + + return 'always'; }, - ); + }); }; diff --git a/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfDataStream.ts b/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfDataStream.ts index 02ba077bfb50..42cdeb24ae2b 100644 --- a/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfDataStream.ts +++ b/packages/fuselage-ui-kit/src/blocks/VideoConferenceBlock/hooks/useVideoConfDataStream.ts @@ -21,7 +21,9 @@ export const useVideoConfDataStream = ({ `${rid}/videoconf`, (id) => id === callId && - queryClient.invalidateQueries(['video-conference', callId]), + queryClient.invalidateQueries({ + queryKey: ['video-conference', callId], + }), ); }, [rid, callId, subscribeNotifyRoom, queryClient]); diff --git a/packages/fuselage-ui-kit/src/elements/ChannelsSelectElement/hooks/useChannelsData.ts b/packages/fuselage-ui-kit/src/elements/ChannelsSelectElement/hooks/useChannelsData.ts index 66019cfcf6e0..9f1ef9909a0e 100644 --- a/packages/fuselage-ui-kit/src/elements/ChannelsSelectElement/hooks/useChannelsData.ts +++ b/packages/fuselage-ui-kit/src/elements/ChannelsSelectElement/hooks/useChannelsData.ts @@ -1,5 +1,5 @@ import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; type useChannelsDataProps = { filter: string; @@ -17,9 +17,10 @@ export const useChannelsData = ({ filter }: useChannelsDataProps) => { '/v1/rooms.autocomplete.channelAndPrivate', ); - const { data } = useQuery( - ['rooms.autocomplete.channelAndPrivate', filter], - async () => { + const { data } = useQuery({ + queryKey: ['rooms.autocomplete.channelAndPrivate', filter], + + queryFn: async () => { const channels = await getRooms(generateQuery(filter)); const options = channels.items.map( @@ -31,10 +32,9 @@ export const useChannelsData = ({ filter }: useChannelsDataProps) => { return options || []; }, - { - keepPreviousData: true, - }, - ); + + placeholderData: keepPreviousData, + }); return data; }; diff --git a/packages/fuselage-ui-kit/src/elements/UsersSelectElement/hooks/useUsersData.ts b/packages/fuselage-ui-kit/src/elements/UsersSelectElement/hooks/useUsersData.ts index 8e807dba8f1c..8e89de4ffd57 100644 --- a/packages/fuselage-ui-kit/src/elements/UsersSelectElement/hooks/useUsersData.ts +++ b/packages/fuselage-ui-kit/src/elements/UsersSelectElement/hooks/useUsersData.ts @@ -1,5 +1,5 @@ import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { keepPreviousData, useQuery } from '@tanstack/react-query'; import type { UserAutoCompleteOptionType } from '../UsersSelectElement'; @@ -10,9 +10,10 @@ type useUsersDataProps = { export const useUsersData = ({ filter }: useUsersDataProps) => { const getUsers = useEndpoint('GET', '/v1/users.autocomplete'); - const { data } = useQuery( - ['users.autoComplete', filter], - async () => { + const { data } = useQuery({ + queryKey: ['users.autoComplete', filter], + + queryFn: async () => { const users = await getUsers({ selector: JSON.stringify({ term: filter }), }); @@ -25,8 +26,9 @@ export const useUsersData = ({ filter }: useUsersDataProps) => { return options || []; }, - { keepPreviousData: true }, - ); + + placeholderData: keepPreviousData, + }); return data; }; diff --git a/packages/mock-providers/package.json b/packages/mock-providers/package.json index a4967947b95d..03f60f0ef31d 100644 --- a/packages/mock-providers/package.json +++ b/packages/mock-providers/package.json @@ -13,7 +13,7 @@ "devDependencies": { "@rocket.chat/ddp-client": "workspace:~", "@rocket.chat/ui-contexts": "workspace:*", - "@tanstack/react-query": "^4.36.1", + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch", "@types/use-sync-external-store": "^0.0.6", "eslint": "~8.45.0", "react": "~17.0.2", diff --git a/packages/mock-providers/src/MockedAppRootBuilder.tsx b/packages/mock-providers/src/MockedAppRootBuilder.tsx index 0eb5256acc14..2856c9e1150f 100644 --- a/packages/mock-providers/src/MockedAppRootBuilder.tsx +++ b/packages/mock-providers/src/MockedAppRootBuilder.tsx @@ -400,11 +400,6 @@ export class MockedAppRootBuilder { queries: { retry: false }, mutations: { retry: false }, }, - logger: { - log: console.log, - warn: console.warn, - error: () => undefined, - }, }); const { connectionStatus, server, router, settings, user, i18n, authorization, wrappers, audioInputDevices, audioOutputDevices } = this; diff --git a/packages/ui-client/src/components/UserAutoComplete/UserAutoComplete.tsx b/packages/ui-client/src/components/UserAutoComplete/UserAutoComplete.tsx index 72a8eecec4d0..9673d716193d 100644 --- a/packages/ui-client/src/components/UserAutoComplete/UserAutoComplete.tsx +++ b/packages/ui-client/src/components/UserAutoComplete/UserAutoComplete.tsx @@ -23,9 +23,10 @@ const UserAutoComplete = ({ value, onChange, ...props }: UserAutoCompleteProps): const debouncedFilter = useDebouncedValue(filter, 1000); const usersAutoCompleteEndpoint = useEndpoint('GET', '/v1/users.autocomplete'); - const { data } = useQuery(['usersAutoComplete', debouncedFilter, conditions], async () => - usersAutoCompleteEndpoint(query(debouncedFilter, conditions)), - ); + const { data } = useQuery({ + queryKey: ['usersAutoComplete', debouncedFilter, conditions], + queryFn: async () => usersAutoCompleteEndpoint(query(debouncedFilter, conditions)), + }); const options = useMemo(() => data?.items.map((user) => ({ value: user.username, label: user.name || user.username })) || [], [data]); diff --git a/packages/ui-voip/package.json b/packages/ui-voip/package.json index 222f16de8a4e..a9bf7dcaa563 100644 --- a/packages/ui-voip/package.json +++ b/packages/ui-voip/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@rocket.chat/emitter": "~0.31.25", - "@tanstack/react-query": "^4.36.1", + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch", "react-i18next": "~13.2.2", "sip.js": "^0.21.2" }, diff --git a/packages/ui-voip/src/components/VoipTransferModal/VoipTransferModal.tsx b/packages/ui-voip/src/components/VoipTransferModal/VoipTransferModal.tsx index f1de589c82b4..72342fa37ee2 100644 --- a/packages/ui-voip/src/components/VoipTransferModal/VoipTransferModal.tsx +++ b/packages/ui-voip/src/components/VoipTransferModal/VoipTransferModal.tsx @@ -21,14 +21,13 @@ const VoipTransferModal = ({ extension, isLoading = false, onCancel, onConfirm } const modalId = useUniqueId(); const getUserInfo = useEndpoint('GET', '/v1/users.info'); - const { data: targetUser, isInitialLoading: isTargetInfoLoading } = useQuery( - ['/v1/users.info', username], - () => getUserInfo({ username }), - { - enabled: Boolean(username), - select: (data) => data?.user || {}, - }, - ); + const { data: targetUser, isLoading: isTargetInfoLoading } = useQuery({ + queryKey: + ['/v1/users.info', username], + queryFn: () => getUserInfo({ username }), + enabled: Boolean(username), + select: (data) => data?.user || {}, + }); const handleConfirm = () => { if (!targetUser?.freeSwitchExtension) { diff --git a/packages/ui-voip/src/hooks/useVoipClient.tsx b/packages/ui-voip/src/hooks/useVoipClient.tsx index fb0aff72d8f3..589f76d7952c 100644 --- a/packages/ui-voip/src/hooks/useVoipClient.tsx +++ b/packages/ui-voip/src/hooks/useVoipClient.tsx @@ -23,9 +23,9 @@ export const useVoipClient = ({ enabled = true, autoRegister = true }: VoipClien const iceServers = useWebRtcServers(); - const { data: voipClient, error } = useQuery( - ['voip-client', enabled, userId, iceServers], - async () => { + const { data: voipClient, error } = useQuery({ + queryKey: ['voip-client', enabled, userId, iceServers], + queryFn: async () => { if (voipClientRef.current) { voipClientRef.current.clear(); } @@ -69,11 +69,9 @@ export const useVoipClient = ({ enabled = true, autoRegister = true }: VoipClien return voipClient; }, - { - initialData: null, - enabled, - }, - ); + initialData: null, + enabled, + }); useEffect(() => { voipClientRef.current = voipClient; diff --git a/packages/ui-voip/src/hooks/useVoipContactId.tsx b/packages/ui-voip/src/hooks/useVoipContactId.tsx index 4ef799ec505e..94d9bb72b258 100644 --- a/packages/ui-voip/src/hooks/useVoipContactId.tsx +++ b/packages/ui-voip/src/hooks/useVoipContactId.tsx @@ -2,7 +2,7 @@ import type { VoipSession } from '../definitions'; import { useVoipExtensionDetails } from './useVoipExtensionDetails'; export const useVoipContactId = ({ session, transferEnabled = true }: { session: VoipSession; transferEnabled?: boolean }) => { - const { data: contact, isInitialLoading: isLoading } = useVoipExtensionDetails({ extension: session.contact.id }); + const { data: contact, isPending: isLoading } = useVoipExtensionDetails({ extension: session.contact.id }); const { data: transferedByContact } = useVoipExtensionDetails({ extension: session.transferedBy?.id, enabled: transferEnabled, diff --git a/packages/ui-voip/src/hooks/useVoipExtensionDetails.tsx b/packages/ui-voip/src/hooks/useVoipExtensionDetails.tsx index d08d6f851638..04a95181b16d 100644 --- a/packages/ui-voip/src/hooks/useVoipExtensionDetails.tsx +++ b/packages/ui-voip/src/hooks/useVoipExtensionDetails.tsx @@ -4,11 +4,11 @@ import { useQuery } from '@tanstack/react-query'; export const useVoipExtensionDetails = ({ extension, enabled = true }: { extension: string | undefined; enabled?: boolean }) => { const isEnabled = !!extension && enabled; const getContactDetails = useEndpoint('GET', '/v1/voip-freeswitch.extension.getDetails'); - const { data, ...result } = useQuery( - ['voip', 'voip-extension-details', extension, getContactDetails], - () => getContactDetails({ extension: extension as string }), - { enabled: isEnabled }, - ); + const { data, ...result } = useQuery({ + queryKey: ['voip', 'voip-extension-details', extension, getContactDetails], + queryFn: () => getContactDetails({ extension: extension as string }), + enabled: isEnabled + }); return { data: isEnabled ? data : undefined, diff --git a/packages/ui-voip/src/hooks/useVoipTransferModal.tsx b/packages/ui-voip/src/hooks/useVoipTransferModal.tsx index df15e400ca27..0471a55d86c4 100644 --- a/packages/ui-voip/src/hooks/useVoipTransferModal.tsx +++ b/packages/ui-voip/src/hooks/useVoipTransferModal.tsx @@ -40,12 +40,12 @@ export const useVoipTransferModal = ({ session }: UseVoipTransferParams) => { setModal( setModal(null)} onConfirm={handleTransfer.mutate} />, ); - }, [handleTransfer.isLoading, handleTransfer.mutate, session, setModal]); + }, [handleTransfer.isPending, handleTransfer.mutate, session, setModal]); return { startTransfer, cancelTransfer: close }; }; diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index bd69a75ccc75..d833208e8b89 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -34,7 +34,7 @@ "@storybook/react": "^8.4.4", "@storybook/react-webpack5": "^8.4.4", "@storybook/theming": "^8.4.4", - "@tanstack/react-query": "^4.36.1", + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch", "@testing-library/react": "~16.0.1", "@types/react": "~17.0.80", "babel-loader": "~9.2.1", diff --git a/packages/web-ui-registration/src/EmailConfirmationForm.tsx b/packages/web-ui-registration/src/EmailConfirmationForm.tsx index 3355081caa31..7f746b66a5a1 100644 --- a/packages/web-ui-registration/src/EmailConfirmationForm.tsx +++ b/packages/web-ui-registration/src/EmailConfirmationForm.tsx @@ -29,7 +29,7 @@ export const EmailConfirmationForm = ({ email, onBackToLogin }: { email?: string return (
{ - if (sendEmail.isLoading) { + if (sendEmail.isPending) { return; } sendEmail.mutate(data.email); @@ -40,7 +40,7 @@ export const EmailConfirmationForm = ({ email, onBackToLogin }: { email?: string {t('registration.page.emailVerification.subTitle')} - + {t('registration.component.form.email')}* @@ -65,7 +65,7 @@ export const EmailConfirmationForm = ({ email, onBackToLogin }: { email?: string - diff --git a/packages/web-ui-registration/src/LoginForm.tsx b/packages/web-ui-registration/src/LoginForm.tsx index 62e757db33c8..3ae19ec28cad 100644 --- a/packages/web-ui-registration/src/LoginForm.tsx +++ b/packages/web-ui-registration/src/LoginForm.tsx @@ -154,7 +154,7 @@ export const LoginForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRoute {showFormLogin && ( <> - + {t('registration.component.form.emailOrUsername')} @@ -213,11 +213,11 @@ export const LoginForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRoute )} - {errorOnSubmit && {renderErrorOnSubmit(errorOnSubmit)}} + {errorOnSubmit && {renderErrorOnSubmit(errorOnSubmit)}} - @@ -229,7 +229,7 @@ export const LoginForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRoute )} - + ); }; diff --git a/packages/web-ui-registration/src/RegisterForm.tsx b/packages/web-ui-registration/src/RegisterForm.tsx index 75ef78db204a..9ea5c6c177fc 100644 --- a/packages/web-ui-registration/src/RegisterForm.tsx +++ b/packages/web-ui-registration/src/RegisterForm.tsx @@ -297,7 +297,7 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo - diff --git a/packages/web-ui-registration/src/hooks/useCheckRegistrationSecret.ts b/packages/web-ui-registration/src/hooks/useCheckRegistrationSecret.ts index 8b6e9c544256..36900ef01977 100644 --- a/packages/web-ui-registration/src/hooks/useCheckRegistrationSecret.ts +++ b/packages/web-ui-registration/src/hooks/useCheckRegistrationSecret.ts @@ -4,10 +4,14 @@ import { useQuery } from '@tanstack/react-query'; export const useCheckRegistrationSecret = (hash?: string) => { const checkRegistrationSecretURL = useMethod('checkRegistrationSecretURL'); - return useQuery(['secretURL', hash], async () => { - if (!hash) { - return false; - } - return checkRegistrationSecretURL(hash); + return useQuery({ + queryKey: ['secretURL', hash], + + queryFn: async () => { + if (!hash) { + return false; + } + return checkRegistrationSecretURL(hash); + }, }); }; diff --git a/yarn.lock b/yarn.lock index a3756b75550c..f89635795d11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8738,7 +8738,7 @@ __metadata: "@storybook/react": "npm:^8.4.4" "@storybook/react-webpack5": "npm:^8.4.4" "@storybook/theming": "npm:^8.4.4" - "@tanstack/react-query": "npm:^4.36.1" + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch" "@testing-library/react": "npm:~16.0.1" "@testing-library/user-event": "npm:~14.5.2" "@types/react": "npm:~17.0.80" @@ -9232,7 +9232,7 @@ __metadata: "@storybook/addon-webpack5-compiler-babel": "npm:^3.0.3" "@storybook/react": "npm:^8.4.4" "@storybook/react-webpack5": "npm:^8.4.4" - "@tanstack/react-query": "npm:^4.36.1" + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch" "@testing-library/react": "npm:~16.0.1" "@testing-library/user-event": "npm:~14.5.2" "@types/adm-zip": "npm:^0.5.6" @@ -9527,7 +9527,7 @@ __metadata: "@rocket.chat/i18n": "workspace:~" "@rocket.chat/ui-contexts": "workspace:*" "@storybook/react": "npm:^8.4.4" - "@tanstack/react-query": "npm:^4.36.1" + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch" "@types/use-sync-external-store": "npm:^0.0.6" eslint: "npm:~8.45.0" i18next: "npm:~23.4.9" @@ -10352,7 +10352,7 @@ __metadata: "@storybook/addon-webpack5-compiler-babel": "npm:^3.0.3" "@storybook/react": "npm:^8.4.4" "@storybook/react-webpack5": "npm:^8.4.4" - "@tanstack/react-query": "npm:^4.36.1" + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch" "@testing-library/react": "npm:~16.0.1" "@testing-library/user-event": "npm:~14.5.2" "@types/jest": "npm:~29.5.14" @@ -10452,7 +10452,7 @@ __metadata: "@storybook/react": "npm:^8.4.4" "@storybook/react-webpack5": "npm:^8.4.4" "@storybook/theming": "npm:^8.4.4" - "@tanstack/react-query": "npm:^4.36.1" + "@tanstack/react-query": "patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch" "@testing-library/react": "npm:~16.0.1" "@types/react": "npm:~17.0.80" babel-loader: "npm:~9.2.1" @@ -11540,29 +11540,32 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:4.36.1": - version: 4.36.1 - resolution: "@tanstack/query-core@npm:4.36.1" - checksum: 10/7c648872cd491bcab2aa4c18e0b7ca130c072f05c277a5876977fa3bfa87634bbfde46e9d249236587d78c39866889a02e4e202b478dc6074ff96093732ae56d +"@tanstack/query-core@npm:5.60.5": + version: 5.60.5 + resolution: "@tanstack/query-core@npm:5.60.5" + checksum: 10/2c85ed3a26db31ea9fb2e44f94afee4564c8a5e47fc2c9f4e7a3b477e90642d1330ecdbc48f3b503205401772cedd94545eff23e628badd2bff5509b1da62e94 languageName: node linkType: hard -"@tanstack/react-query@npm:^4.36.1": - version: 4.36.1 - resolution: "@tanstack/react-query@npm:4.36.1" +"@tanstack/react-query@npm:5.60.5": + version: 5.60.5 + resolution: "@tanstack/react-query@npm:5.60.5" dependencies: - "@tanstack/query-core": "npm:4.36.1" - use-sync-external-store: "npm:^1.2.0" + "@tanstack/query-core": "npm:5.60.5" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-native: "*" - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - checksum: 10/764b860c3ac8d254fc6b07e01054a0f58058644d59626c724b213293fbf1e31c198cbb26e4c32c0d16dcaec0353c0ae19147d9c667675b31f8cea1d64f1ff4ac + react: ^18 || ^19 + checksum: 10/00a5ef74ceb50f6bbacec2545392de65d3d9e6dc6de2a7107943460a83d1988eb66740f40b8682c8de0e9a1faff76256ab1584a816c70dd4ff9205dedc209f0a + languageName: node + linkType: hard + +"@tanstack/react-query@patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch": + version: 5.60.5 + resolution: "@tanstack/react-query@patch:@tanstack/react-query@npm%3A5.60.5#~/.yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch::version=5.60.5&hash=287929" + dependencies: + "@tanstack/query-core": "npm:5.60.5" + peerDependencies: + react: ^18 || ^19 + checksum: 10/dbb0bb6598f5d095a2d632eade1c1b1b586e24befc6538412bde03a0dc6627a0ed0cde27974e9afeb2a406cc6ff08a2ada6ae497c81b819a4fd1d0c0ae4ed50a languageName: node linkType: hard @@ -38647,7 +38650,7 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:1.2.2, use-sync-external-store@npm:^1.2.0, use-sync-external-store@npm:^1.2.2, use-sync-external-store@npm:~1.2.0, use-sync-external-store@npm:~1.2.2": +"use-sync-external-store@npm:1.2.2, use-sync-external-store@npm:^1.2.2, use-sync-external-store@npm:~1.2.0, use-sync-external-store@npm:~1.2.2": version: 1.2.2 resolution: "use-sync-external-store@npm:1.2.2" peerDependencies: