SWR dependency installed but never used — 50+ components silently suffering from race conditions and duplicate requests

Finding

While auditing the frontend codebase, I discovered that swr@2.0.3 is listed as a dependency in package.json — but a full codebase search confirms it is imported zero times across the entire application.

Meanwhile, data fetching is manually handled in 50+ component files using the pattern:

useEffect(() => {
  fetch(url)
    .then(res => res.json())
    .then(data => setData(data))
}, [])

Why this silently hurts users right now

But three things are happening invisibly:

  1. Race conditions — if a user navigates away before a slow fetch resolves, the setState still fires on an unmounted component. No cleanup function = potential memory leak and stale state override.

  2. Duplicate network requests — if two components on the same dashboard both need the same data, two identical requests go out. SWR would deduplicate these automatically.

  3. No background sync — when a lab technician switches tabs and comes back, the data is stale but shows no indication. SWR’s stale-while-revalidate would silently refresh it in the background.

The fix — replacing one component as proof of concept

Replace the fetch pattern in analyzerService.js with a single custom SWR hook:

// Before — in every component that needs analyzer data
const [data, setData] = useState(null)
useEffect(() => {
  fetch('/api/analyzers').then(r => r.json()).then(setData)
}, [])

// After — one shared hook in /src/hooks/useAnalyzers.js
import useSWR from 'swr'
const fetcher = url => fetch(url).then(r => r.json())

export function useAnalyzers() {
  const { data, error, isLoading } = useSWR('/api/analyzers', fetcher)
  return { analyzers: data, error, isLoading }
}

Every component that needs analyzer data now calls useAnalyzers() — one line, zero useEffect, zero manual state, race conditions gone, caching automatic.

Impact if fully adopted

The same pattern scales to every data domain in the app. The dependency is already paid for and installed. This is purely an adoption gap, not a new dependency decision.

Proposed first step

I’d like to start by converting one high-traffic component (e.g., the analyzer dashboard) as a proof-of-concept PR, document the custom hook pattern, and open discussion on standardizing this across src/services/.

2 Likes

Hey @priyanshu56 I have also looked into it and it should be started now as the codebase is getting bigger.