Camilo Tavera
Posts

Mastering `useEffect`: The Right Way to Use React’s Most Misused Hook

Camilo Tavera
May 10, 2025

A concise guide to using useEffect properly in React—covering common mistakes, best practices, dependency management, and when to avoid it for cleaner, more efficient components.

As a Senior Software Engineer, I’ve seen countless pull requests where useEffect is either doing too much or doing it wrong. And I get it—useEffect is deceptively simple. At first glance, it looks like a catch-all for side effects in React, but if you treat it like a hammer, everything starts to look like a nail.

In this post, I want to walk through what I’ve learned about using useEffect correctly, with real-world examples and mental models that help keep code predictable, clean, and performant.


💡 First: What is useEffect for?#

At its core, useEffect is a way to run side effects in function components—anything that affects something outside the scope of the function itself:

  • Fetching data
  • Subscribing to events
  • Updating the DOM manually
  • Working with timers or intervals

But here’s the thing: not all logic needs to go inside useEffect.


🚫 Common Misuse: Treating useEffect as componentDidUpdate#

A common anti-pattern I see looks like this:

This looks fine, but there’s a catch: this derived state should live in a computed value, not state + effect. It creates unnecessary renders and complexity.

✅ Better:


✅ Rule of Thumb #1: Keep it pure, keep it simple#

Your useEffect should ideally:

  • Do one thing.
  • Be focused on effects: subscriptions, async calls, DOM interactions.
  • Not calculate derived state—leave that to useMemo or inline logic.

🔄 Rule of Thumb #2: Dependencies should match what you use#

If you're using a variable inside useEffect, it should be in the dependency array. Period.

Bad:

Good:

If you’re fighting with the dependency array, that’s a sign the logic may belong elsewhere—or needs refactoring.


🧹 Cleanups Matter: Always return a function if you open something#

Cleanups prevent memory leaks and unexpected behaviors, especially in components that mount and unmount frequently.


🧠 Final Thoughts: Don’t use useEffect until you need to#

Whenever I write a new component, I wait until I truly need an effect. Ask:

  • Can this be derived from props or state?
  • Is this really a side effect?
  • Am I just trying to replicate lifecycle behavior from class components?

Less useEffect usually means simpler code.


🚀 Takeaway#

Mastering useEffect means understanding when not to use it as much as when to reach for it. Keep effects focused, predictable, and side-effectful (pun intended). It’ll make your components easier to test, debug, and scale.


Want to see real-world examples or code audits? Check out my portfolio at iamcamilotavera.com or reach out for a code review.