diff --git a/app/components/invalidate-queries.tsx b/app/components/invalidate-queries.tsx index 56161a36..3bb656e0 100644 --- a/app/components/invalidate-queries.tsx +++ b/app/components/invalidate-queries.tsx @@ -1,31 +1,17 @@ "use client" import { useTaskHistoryWebSocket } from "@renegade-fi/react" -import { Query, useQueryClient } from "@tanstack/react-query" +import { useQueryClient } from "@tanstack/react-query" + +import { shouldInvalidate } from "@/lib/query" export function InvalidateQueries() { const queryClient = useQueryClient() useTaskHistoryWebSocket({ onUpdate: (task) => { if (task.state === "Completed") { - // TODO: Only invalidate queries related to wallet state - // queryClient.invalidateQueries() - const nonStaticQueries = (query: Query) => { - const defaultStaleTime = - queryClient.getQueryDefaults(query.queryKey).staleTime ?? 0 - const staleTimes = query.observers - .map((observer) => observer.options.staleTime ?? Infinity) - .filter((staleTime): staleTime is number => staleTime !== undefined) - - const staleTime = - query.getObserversCount() > 0 - ? Math.min(...staleTimes) - : defaultStaleTime - - return staleTime !== Number.POSITIVE_INFINITY - } queryClient.invalidateQueries({ - predicate: nonStaticQueries, + predicate: (query) => shouldInvalidate(query, queryClient), }) } }, diff --git a/lib/query.ts b/lib/query.ts index 3647be07..9afe8158 100644 --- a/lib/query.ts +++ b/lib/query.ts @@ -1,7 +1,35 @@ import { Exchange, getDefaultQuoteToken, Token } from "@renegade-fi/react" +import { Query, QueryClient } from "@tanstack/react-query" import { remapToken } from "@/lib/token" +// Helper function defining a global rule for invalidating queries +// We invalidate queries that are: +// - Not static (finite stale time) +// - Not a price query +// +// TODO: We should invalidate queries related to wallet / on-chain state +// We apply a general global rule for now because it doesn't hurt to have fresh data. +export function shouldInvalidate(query: Query, queryClient: QueryClient) { + // If the query is a price query, don't invalidate + if (query.queryKey.includes("price")) { + return false + } + + // Invalidate if the effective stale time is not set to infinite. + const defaultStaleTime = + queryClient.getQueryDefaults(query.queryKey).staleTime ?? 0 + + const staleTimes = query.observers + .map((observer) => observer.options.staleTime ?? Infinity) + .filter((staleTime): staleTime is number => staleTime !== undefined) + + const effectiveStaleTime = + query.getObserversCount() > 0 ? Math.min(...staleTimes) : defaultStaleTime + + return effectiveStaleTime !== Number.POSITIVE_INFINITY +} + export async function getPriceFromPriceReporter( topic: string, ): Promise { diff --git a/providers/query-provider.tsx b/providers/query-provider.tsx index ca168086..0fe1d009 100644 --- a/providers/query-provider.tsx +++ b/providers/query-provider.tsx @@ -8,6 +8,8 @@ import { Query, } from "@tanstack/react-query" +import { shouldInvalidate } from "@/lib/query" + function makeQueryClient(mutationCache?: MutationCache) { return new QueryClient({ defaultOptions: { @@ -38,29 +40,11 @@ function getQueryClient(mutationCache?: MutationCache) { } export function QueryProvider({ children }: { children: React.ReactNode }) { - // NOTE: Avoid useState when initializing the query client if you don't - // have a suspense boundary between this and the code that may - // suspend because React will throw away the client on the initial - // render if it suspends and there is no boundary const queryClient = getQueryClient( new MutationCache({ onSuccess: (_data, _variables, _context, mutation) => { - const nonStaticQueries = (query: Query) => { - const defaultStaleTime = - queryClient.getQueryDefaults(query.queryKey).staleTime ?? 0 - const staleTimes = query.observers - .map((observer) => observer.options.staleTime ?? Infinity) - .filter((staleTime): staleTime is number => staleTime !== undefined) - - const staleTime = - query.getObserversCount() > 0 - ? Math.min(...staleTimes) - : defaultStaleTime - - return staleTime !== Number.POSITIVE_INFINITY - } queryClient.invalidateQueries({ - predicate: nonStaticQueries, + predicate: (query) => shouldInvalidate(query, queryClient), }) }, onError: (error, _variables, _context, mutation) => {