DEV Community

Cover image for I Stopped Using useEffect for Data Fetching in React
Ferry Ananda Febian
Ferry Ananda Febian

Posted on

I Stopped Using useEffect for Data Fetching in React

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.

Example hooks with SWR

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 🚀

https://swr.vercel.app/

Top comments (1)

Collapse
 
ferryops profile image
Ferry Ananda Febian

reserved()