Skip to content

fix(frontend): notification panel never fetches list on bell click#495

Open
TatsuKo-Tsukimi wants to merge 1 commit intodataelement:mainfrom
TatsuKo-Tsukimi:fix/bell-disabled-refetch
Open

fix(frontend): notification panel never fetches list on bell click#495
TatsuKo-Tsukimi wants to merge 1 commit intodataelement:mainfrom
TatsuKo-Tsukimi:fix/bell-disabled-refetch

Conversation

@TatsuKo-Tsukimi
Copy link
Copy Markdown

Bug

Clicking the notification bell opens the panel but always shows "暂无通知 / No notifications" even when the unread badge displays a positive count. The unread number then stays stuck — closing and reopening doesn't help.

Root cause

Layout.tsx calls refetchNotifications() synchronously inside the bell's onClick, right after setShowNotifications(v => !v). At that moment the query is still enabled: !!user && showNotifications with showNotifications === false (state hasn't committed yet), so the manual refetch doesn't actually hit /api/notifications.

Empirical evidence from dev backend logs: 300+ hits on GET /api/notifications/unread-count (the polling badge), zero on GET /api/notifications (the list endpoint). With the list never fetched, notifications stays [] (the panel shows "暂无通知") and markOneRead / markAllRead are never reachable — that's why the badge can never decrement.

Fix

Drop the manual refetch entirely. TanStack Query v5's queryObserver.shouldFetchOptionally already auto-fetches when enabled flips false → true (the prevOptions.enabled === false branch with stale data).

Verified on dev

After the fix, every bell interaction now produces the expected backend call:

  • Click bell → GET /api/notifications?limit=50 → 200 (panel populates)
  • Switch tabs → ?category=tool|approval|social → 200 each
  • Click an item → POST /api/notifications/{id}/read → 200 (badge -1)
  • "全部已读" → POST /api/notifications/read-all → 200 (badge → 0)

The bell's onClick called refetchNotifications() synchronously after
setShowNotifications(v => !v). At that moment useQuery is still
enabled: false (state hasn't committed), so the manual refetch never
hit /api/notifications -- empirically 0 list calls vs 300+ unread-count
polls in dev logs. The panel always showed "暂无通知" and the unread
badge could never decrement (no list = nothing to mark as read).

Drop the manual refetch and let v5 auto-fetch when enabled flips
false -> true (queryObserver.shouldFetchOptionally already covers this).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@TatsuKo-Tsukimi
Copy link
Copy Markdown
Author

Note on local repro — heard this isn't manifesting on at least one local dev setup. A couple of things that may help isolate it:

Reproduction checklist:

  1. Test account must have ≥1 unread notification (badge > 0)
  2. Open DevTools → Network → filter by notifications
  3. Click the bell, watch for GET /api/notifications?limit=50

The buggy state and the no-unread state look identical in the panel ("暂无通知"), so the network tab is the reliable signal.

Possible dev-vs-prod divergence:

Verification here was on a vite build + nginx production bundle. If local testing is via npm run dev, a few plausible reasons the symptom might be masked:

  • React.StrictMode double-mounts on first render, changing QueryObserver subscription timing
  • Vite HMR can preserve query cache across hot reloads — a list fetched during an earlier edit could still be cached
  • React 19's dev-mode event-handler ordering can differ slightly from prod

None of these are things I could prove from a static read; they're just common axes for "works in dev, broken in prod" discrepancies.

Empirical state on the deployed dev env (vite build bundle):

  • Before fix: 0 hits on GET /api/notifications across 300+ unread-count polls; UI showed empty panel while badge displayed 13
  • After fix: full flow works end-to-end (list / mark-one / read-all)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant