diff --git a/packages/reference/src/common/EntityStore.tsx b/packages/reference/src/common/EntityStore.tsx index e03a07339..517b19f94 100644 --- a/packages/reference/src/common/EntityStore.tsx +++ b/packages/reference/src/common/EntityStore.tsx @@ -1,16 +1,7 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { BaseAppSDK } from '@contentful/app-sdk'; -import { - FetchQueryOptions, - Query, - QueryCache, - QueryClient, - QueryClientProvider, - QueryKey, - useQuery, - useQueryClient, -} from '@tanstack/react-query'; +import { FetchQueryOptions, Query, QueryKey } from '@tanstack/react-query'; import constate from 'constate'; import { PlainClientAPI, createClient } from 'contentful-management'; import PQueue from 'p-queue'; @@ -24,6 +15,7 @@ import { ScheduledAction, Space, } from '../types'; +import { SharedQueryClientProvider, useQuery, useQueryClient } from './queryClient'; export type ResourceInfo = { resource: R; @@ -462,29 +454,10 @@ export function useResource(resourceType: ResourceType, urn: string, options?: U } function EntityProvider({ children, ...props }: React.PropsWithChildren) { - const reactQueryClient = useMemo(() => { - const queryCache = new QueryCache(); - const queryClient = new QueryClient({ - queryCache, - defaultOptions: { - queries: { - useErrorBoundary: false, - refetchOnWindowFocus: false, - refetchOnReconnect: true, - refetchOnMount: false, - staleTime: Infinity, - retry: false, - }, - }, - }); - - return queryClient; - }, []); - return ( - + {children} - + ); } diff --git a/packages/reference/src/common/queryClient.tsx b/packages/reference/src/common/queryClient.tsx new file mode 100644 index 000000000..d34538500 --- /dev/null +++ b/packages/reference/src/common/queryClient.tsx @@ -0,0 +1,47 @@ +import * as React from 'react'; + +import { QueryClient, useQuery as useRQ } from '@tanstack/react-query'; + +/** + * A custom client context ensures zero conflict with host apps also using + * React Query. + */ +const clientContext = React.createContext(undefined); + +export function useQueryClient(): QueryClient { + const client = React.useContext(clientContext); + + return React.useMemo(() => { + if (client) { + return client; + } + + return new QueryClient({ + defaultOptions: { + queries: { + useErrorBoundary: false, + refetchOnWindowFocus: false, + refetchOnReconnect: true, + refetchOnMount: false, + staleTime: Infinity, + retry: false, + }, + }, + }); + }, [client]); +} + +// @ts-expect-error +export const useQuery: typeof useRQ = (key, fn, opt) => { + return useRQ(key, fn, { ...opt, context: clientContext }); +}; + +/** + * Provides access to a query client either by sharing an existing client or + * creating a new one. + */ +export function SharedQueryClientProvider({ children }: React.PropsWithChildren<{}>) { + const client = useQueryClient(); + + return {children}; +} diff --git a/packages/reference/src/index.tsx b/packages/reference/src/index.tsx index f1b0a0678..f9884f872 100644 --- a/packages/reference/src/index.tsx +++ b/packages/reference/src/index.tsx @@ -23,6 +23,7 @@ export type { } from './common/customCardTypes'; export { SortableLinkList } from './common/SortableLinkList'; export { EntityProvider, useEntityLoader, useEntity, useResource } from './common/EntityStore'; +export { SharedQueryClientProvider as EntityCacheProvider } from './common/queryClient'; export type { ResourceInfo } from './common/EntityStore'; export { SingleResourceReferenceEditor, MultipleResourceReferenceEditor } from './resources'; export * from './types';