Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 193 additions & 0 deletions .claude/fix-navigation-caching-bug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# Navigation Caching Bug Fix

## Bug Report

**Issue:** When navigating from the main dashboard to another page (e.g., /help) and then back, tables show "no data found" messages and status indicators display loading spinners indefinitely until the page is manually refreshed.

## Root Cause Analysis

### Problem

React Query caching configuration was inconsistent and incomplete across API hooks:

1. **Missing `staleTime` Configuration:**
- Default `staleTime` is `0`, meaning data becomes stale immediately after fetching
- Some hooks had no `staleTime` configured: `useChainInfo`, `useListCollections`, `useAuditLogs`, `useMetrics`
- Only `usePeers` and `useValidator` had refresh intervals configured

2. **Disabled `refetchOnWindowFocus`:**
- Global QueryClient configuration disabled automatic refetching when window regains focus
- This is intentional for the application, but required proper `refetchOnMount` configuration

3. **Missing `refetchOnMount` Configuration:**
- No explicit `refetchOnMount: true` on individual hooks
- When navigating back to a page, stale cached data would be displayed without refetching

### How the Bug Manifested

**Navigation Flow:**
1. User loads dashboard → All hooks fetch data successfully
2. User navigates to /help → Dashboard component unmounts
3. React Query retains cached data with `staleTime: 0` (immediately stale)
4. User navigates back to dashboard → Dashboard component remounts
5. React Query returns stale cached data
6. Without `refetchOnMount: true`, queries don't refetch fresh data
7. Component renders with stale/empty data or stuck loading state

## Solution Implemented

### 1. Global QueryClient Configuration

Updated `web/apps/dashboard/src/App.tsx`:

```typescript
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false, // Keep disabled (intentional)
refetchOnMount: true, // ✅ Added: Always refetch on mount
staleTime: 30000, // ✅ Added: 30s default freshness
retry: 1,
},
},
})
```

**Benefits:**
- Provides sensible defaults for all queries
- Ensures data refetches when components mount
- 30-second freshness window prevents unnecessary refetches

### 2. Hook-Specific Configuration

Added `refetchOnMount: true` and `staleTime` to all query hooks:

#### `useChainInfo` (web/packages/hooks/src/api/useBlockchain.ts)
```typescript
refetchOnMount: true,
staleTime: 10000, // 10s freshness
```

#### `useListCollections` (web/packages/hooks/src/api/useListCollections.ts)
```typescript
refetchOnMount: true,
staleTime: 10000, // 10s freshness
```

#### `useAuditLogs` (web/packages/hooks/src/api/useAuditLogs.ts)
```typescript
refetchOnMount: true,
staleTime: 5000, // 5s freshness (more volatile)
```

#### `useMetrics` (web/packages/hooks/src/api/useMetrics.ts)
```typescript
refetchOnMount: true,
staleTime: 10000, // 10s freshness
```

**Note:** `usePeers` and `useValidator` already had `refetchInterval` configured, which implicitly handles staleness.

### 3. Stale Time Strategy

Different `staleTime` values based on data volatility:

- **5 seconds:** Audit logs (high-frequency updates)
- **10 seconds:** Chain info, collections, metrics (moderate updates)
- **30 seconds:** Default fallback (low-frequency data)
- **Refresh intervals:** Peers (5s), validator (10s) - override staleTime

## Prevention Strategy

### Code Standards

1. **Always Configure Query Hooks:**
```typescript
export function useMyData() {
return useQuery({
queryKey: ['my-data'],
queryFn: fetchMyData,
refetchOnMount: true, // ✅ Required
staleTime: 10000, // ✅ Required (adjust based on volatility)
})
}
```

2. **Mutation Hooks Don't Need Caching:**
- `useMutation` hooks (`useSubmitData`, `useDecryptData`, etc.) don't need `staleTime`
- Mutations should invalidate related queries using `queryClient.invalidateQueries()`

3. **Refresh Intervals Override Staleness:**
- If using `refetchInterval`, explicit `staleTime` is optional
- Interval keeps data perpetually fresh
- Example: `usePeers` with `refetchInterval: 5000`

### Testing Checklist

When implementing new query hooks, verify:

- [ ] `refetchOnMount: true` configured
- [ ] `staleTime` set based on data volatility
- [ ] Navigation away and back shows fresh data
- [ ] No infinite loading spinners
- [ ] No "no data found" errors on navigation back
- [ ] Console shows expected refetch behavior

### Architecture Patterns

**Query Invalidation After Mutations:**
```typescript
export function useSubmitData() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: submitDataFn,
onSuccess: () => {
// ✅ Invalidate related queries to trigger refetch
queryClient.invalidateQueries({ queryKey: ['collections'] })
},
})
}
```

**Conditional Query Enabling:**
```typescript
export function useAuditLogs(params, enabled = true) {
return useQuery({
queryKey: ['audit-logs', params],
enabled, // ✅ Allow conditional fetching
queryFn: fetchAuditLogs,
refetchOnMount: true,
staleTime: 5000,
})
}
```

## Files Modified

1. `web/apps/dashboard/src/App.tsx` - Global QueryClient config
2. `web/packages/hooks/src/api/useBlockchain.ts` - useChainInfo config
3. `web/packages/hooks/src/api/useListCollections.ts` - useListCollections config
4. `web/packages/hooks/src/api/useAuditLogs.ts` - useAuditLogs config
5. `web/packages/hooks/src/api/useMetrics.ts` - useMetrics config

## Verification

To verify the fix:

1. Start the application
2. Navigate to dashboard and observe data loading
3. Navigate to any other page (e.g., /submit, /collections)
4. Navigate back to dashboard
5. **Expected:** Data refetches and displays correctly
6. **Expected:** No indefinite loading spinners
7. **Expected:** No "no data found" messages

## Related Documentation

- [React Query Caching](https://tanstack.com/query/latest/docs/react/guides/caching)
- [React Query refetchOnMount](https://tanstack.com/query/latest/docs/react/guides/important-defaults)
- [CLAUDE.md Web Development Architecture](/workspace/CLAUDE.md#web-development-architecture)

## Date

2025-11-04
Loading
Loading