For a long time, useEffect was my default tool for handling data fetching in React. It worked but it never felt right.
After adopting SWR, especially its mutate API, I realized something important:
Data fetching is not a side effect.
Once I embraced that idea, useEffect slowly disappeared from my data-fetching logic.
The Problem with useEffect for Fetching Data
Using useEffect to fetch data usually looks like this:
- Track dependencies carefully
- Handle loading state manually
- Handle error state manually
- Prevent infinite loops
- Sync UI updates with async behavior
As the application grows, this approach becomes:
- Hard to reason about
- Easy to break
- Difficult to reuse
Most of the complexity comes from treating data fetching as an imperative side effect, rather than part of application state.
SWR Changed My Mental Model
With SWR, data fetching becomes declarative.
Instead of asking:
“When should I fetch this data?”
You describe:
“This component needs this data.”
SWR handles:
- Caching
- Revalidation
- Deduplication
- Loading and error states
And most importantly, it exposes mutate.
Why mutate Replaced useEffect for Me
mutate allows you to:
- Update cached data directly
- Perform optimistic updates
- Revalidate data with a single function call
This means:
- No manual refetch logic
- No dependency arrays
- No duplicated fetching code
Fetching and updating data becomes intent-based, not lifecycle-based.
useEffect vs mutate (SWR)
useEffect
- Imperative data fetching
- Manual dependency management
- Boilerplate for loading and error state
- Prone to race conditions
- Fetch logic often scattered across components
mutate (SWR)
- Declarative data updates
- Built-in cache and revalidation
- One-line refetch or optimistic update
- Centralized and reusable logic
- UI stays in sync with cache automatically
When I Still Use useEffect
I still use useEffect but only for true side effects, such as:
- Event listeners
- Subscriptions
- Timers
- Direct DOM interactions
Not for data fetching.
Final Thoughts
Once you treat data as state, not a side effect, your React code becomes:
- Cleaner
- More predictable
- Easier to maintain
If you’re still relying heavily on useEffect for data fetching, I highly recommend trying SWR and its mutate API.
You might never look back 🚀

Top comments (1)
reserved()