React Patterns I Stopped Using (And What Replaced Them)
Some patterns that were once considered best practice have better alternatives today. Here's what I removed from my codebase and why.
React's API has stabilized, but "best practice" is still a moving target. Looking back at code I wrote two years ago, a few patterns stand out as things I'd do differently today — not because they're broken, but because better alternatives exist.
useEffect for Data Fetching
This one is well-documented but still everywhere in codebases:
The problems: no error handling, no cleanup, no deduplication, re-fetches on every render cycle change.
What I use now is SWR or React Query, or in Next.js App Router, just making the component async:
Prop Drilling Solved by Context (When It Shouldn't Be)
Context is for truly global state — theme, auth, locale. I used to reach for it whenever prop drilling got annoying. The problem is that every context consumer re-renders when the value changes, which creates subtle performance bugs.
The better solution for most cases is component composition:
Lift the component itself up, not the data.
Boolean Props for Variants
Explicit variant props are cleaner:
This is exactly what class-variance-authority enforces — and why shadcn/ui uses it.
React.FC Type Annotation
React.FC implicitly includes children in older React versions (it no longer does in React 18+), and the function declaration form handles generics better, reads more clearly in stack traces, and lets you use export default function without a separate declaration.
None of these are sins — they're patterns that made sense at the time. The point isn't to rewrite working code, but to recognize when the new approach is strictly better for fresh code.