Post on: 2024-12-10Last edited: 2026-6-12Words 635Read Time 2 min

type
Post
status
Published
date
Dec 10, 2024
slug
avoid-excessive-useeffect
summary
useEffect is useful for side effects outside rendering, but too many effects turn a component into a dependency maze. This post uses a concrete dashboard example to show when to extract custom hooks or move data fetching elsewhere.
tags
Development
Website building
Tools
category
Technology
icon
password
paired_with
1581d487-a2a1-80dc-abac-e7c009edea02
lang
translation_locked
source_hash
b8a94d017af2dbaefecd61ab5667f3b3555f55c1eedb981979a88da011671844
💭
useEffect is one of those React hooks that looks convenient until it quietly turns a component into something nobody wants to touch. I have written enough projects that were beaten up by messy effects to become a little cautious. This post is about when I use useEffect, when I try not to use it, and how I clean things up when an effect is unavoidable.

What A Side Effect Is

In React, a side effect is anything that happens outside the pure rendering process. For example:
  • Calling an API
  • Mutating the DOM directly
  • Subscribing to an external data source
  • Setting a timer or event listener
These things are not rendering itself, but they can affect what the user eventually sees. React does not automatically know when they happen, so useEffect gives you an escape hatch.

What useEffect Looks Like

Declarative setup, cleanup functions, dependency tracking - it all looks nice. The trouble starts when one component has five or six effects, each watching a different dependency.

The Version That Hurts

I have written code like this before. Looking back, I want to stop my past self.
There are four effects scattered through the component. Each one watches its own dependency. It is hard to see what runs first, what triggers what, and which update causes another render. Add some useCallback and useMemo, and the component enters the "do not touch this" zone.

How I Write It Now

My rule is simple: not every side effect needs to live directly inside the component. If I can move it out, I move it out. The usual options are:
  1. Put related side effects into a custom hook, so the component calls one line.
  1. Use React Query, SWR, or server components for data fetching instead of writing fetch logic in effects.
  1. When an effect is really needed, pay close attention to the dependency array and cleanup function.
Here is a cleaner version of the dashboard example:
The mounted flag prevents state updates after the component unmounts. Without some form of cleanup, the red warning in the console will eventually find you.

Bottom Line

useEffect is not the problem. Using it for everything is the problem. Before I write a new effect, I now ask: "Does this truly need to happen after render?" If the answer is "not really," it probably belongs outside the component or inside a dedicated hook.

References


Loading...
Auto-Scrolling AI Chats: How to Read User Intent

Auto-Scrolling AI Chats: How to Read User Intent

Auto-scroll in an AI chat is not just scrollTop. It needs intent signals, a follow/free state machine, handling for programmatic scroll events, virtualization, and mobile edge cases.


How AI Coding Assistants Actually Improve Developer Efficiency

How AI Coding Assistants Actually Improve Developer Efficiency

Based on hands-on use of Copilot, Cursor, and Claude Code, this post separates where AI assistants help most, such as search, boilerplate, and error diagnosis, from where they still struggle, such as architecture and edge cases.


Announcement
This site is still updating…