Prevent individual queries from racing with batch queries

useAuthor and useEventStats were firing individual queries simultaneously
with the batch hooks (useAuthors, useBatchEventStats), causing a flood of
concurrent relay subscriptions. Each NoteCard's useAuthor created its own
kind:0 query even though useAuthors in Feed.tsx was about to fetch the
same data in a single batched query.

Fix: Use useIsFetching to detect when a batch query is in-flight and
disable individual queries until the batch completes. The batch seeds
individual cache entries, so useAuthor/useEventStats resolve instantly
from cache without ever firing their own relay queries.

On pages without batch queries (PostDetailPage, NotificationsPage, etc.),
batchFetching === 0 immediately, so individual hooks fire normally.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy
2026-02-18 01:53:12 -06:00
parent 0fa3e58a83
commit 25b2e274be
2 changed files with 14 additions and 3 deletions
+8 -1
View File
@@ -1,10 +1,14 @@
import { type NostrEvent, type NostrMetadata, NSchema as n } from '@nostrify/nostrify';
import { useNostr } from '@nostrify/react';
import { useQuery } from '@tanstack/react-query';
import { useQuery, useIsFetching } from '@tanstack/react-query';
export function useAuthor(pubkey: string | undefined) {
const { nostr } = useNostr();
// If a batch author query (useAuthors) is currently in-flight, wait for
// it to finish and seed our cache instead of firing an individual query.
const batchFetching = useIsFetching({ queryKey: ['authors'] });
return useQuery<{ event?: NostrEvent; metadata?: NostrMetadata }>({
queryKey: ['author', pubkey ?? ''],
queryFn: async ({ signal }) => {
@@ -30,5 +34,8 @@ export function useAuthor(pubkey: string | undefined) {
},
staleTime: 5 * 60 * 1000, // Keep cached data fresh for 5 minutes
retry: 1,
// Don't fire this individual query while a batch is in progress —
// the batch will seed our cache entry when it completes.
enabled: !!pubkey && batchFetching === 0,
});
}
+6 -2
View File
@@ -1,5 +1,5 @@
import { useNostr } from '@nostrify/react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useQuery, useQueryClient, useIsFetching } from '@tanstack/react-query';
import type { NostrEvent } from '@nostrify/nostrify';
export interface TrendingTag {
@@ -181,6 +181,10 @@ function computeStats(eventId: string, events: NostrEvent[]): EventStats {
export function useEventStats(eventId: string | undefined) {
const { nostr } = useNostr();
// If a batch stats query (useBatchEventStats) is currently in-flight, wait
// for it to finish and seed our cache instead of firing an individual query.
const batchFetching = useIsFetching({ queryKey: ['batch-event-stats'] });
return useQuery({
queryKey: ['event-stats', eventId ?? ''],
queryFn: async ({ signal }) => {
@@ -199,7 +203,7 @@ export function useEventStats(eventId: string | undefined) {
return computeStats(eventId, events);
},
enabled: !!eventId,
enabled: !!eventId && batchFetching === 0,
staleTime: 60 * 1000,
placeholderData: (prev) => prev,
});