From a8afb9cd58145657d1fa97457ffcb56ec11bfc17 Mon Sep 17 00:00:00 2001 From: Derek Ross Date: Sun, 1 Mar 2026 19:07:59 -0500 Subject: [PATCH] Fix Activity tab query stability The follower-rsvps query was unreliable due to: 1. Stale closure: followedPubkeys was captured at render time but the queryKey only included the user pubkey, not the actual follow list. When the follow list loaded asynchronously, the queryFn could run with an empty or stale array. Now the queryKey includes a stable hash of the first 20 followed pubkeys so it re-runs when the follow list actually changes. 2. followedPubkeys defaulting to []: when followData was undefined (still loading), the default [] made hasFollows false, but on the next render when followData arrived, the query might not re-fetch because the stale cached result from the empty run was returned. Now followedPubkeys is undefined until loaded, and isReady properly gates the query. The React warning about setState during render in useLayoutOptions is a known pattern used by all pages and is not specific to EventsFeedPage. --- src/pages/EventsFeedPage.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/pages/EventsFeedPage.tsx b/src/pages/EventsFeedPage.tsx index b47ee06f..9fabe1aa 100644 --- a/src/pages/EventsFeedPage.tsx +++ b/src/pages/EventsFeedPage.tsx @@ -175,15 +175,24 @@ function ActivitySection() { const [loginDialogOpen, setLoginDialogOpen] = useState(false); const { startSignup } = useOnboarding(); - const followedPubkeys = followData?.pubkeys ?? []; - const hasFollows = followedPubkeys.length > 0; + const followedPubkeys = followData?.pubkeys; + const hasFollows = !!followedPubkeys && followedPubkeys.length > 0; const isReady = !!user && hasFollows; + // Stable key that changes when the follow list actually changes + const followsKey = useMemo( + () => followedPubkeys ? followedPubkeys.slice(0, 20).join(',') : '', + [followedPubkeys], + ); + // Fetch RSVPs from followed users const rsvpQuery = useInfiniteQuery({ - queryKey: ['follower-rsvps', user?.pubkey ?? ''], + queryKey: ['follower-rsvps', user?.pubkey ?? '', followsKey], queryFn: async ({ pageParam }) => { - if (!user || !hasFollows) return { rsvps: [], oldestTimestamp: 0, rawCount: 0 }; + // Re-read from the outer scope — these are captured at call time, not mount time + if (!followedPubkeys || followedPubkeys.length === 0) { + return { rsvps: [], oldestTimestamp: 0, rawCount: 0 }; + } const signal = AbortSignal.timeout(8000); const filter: Record = {