UseEffect를 거의 사용하지 않는 이유 ep1

작성자

카테고리:

← 피드로
DEV Community · Alejandro · 2026-07-15 개발(SW)

Alejandro

Alejandro

Posted on Jul 15 • Edited on Jul 16

When I started learning React, I thought useEffect was the solution to almost everything. To derive state, to fetch data, to synchronize props or calculate a value, the answer for all this was useEffect.
After working on larger applications, i realized most of those effects weren’t needed at all.
Today, I probably write 80% fewer useEffects than I did a few years ago. Not because it’s a bad hook but because most problems have simpler solutions.
This article is the first part of my Modern React Patterns series, where I go over patterns that worked fine in small demos but became painful in production.

What useEffect Is Actually For

The React documentation describes effects as a way to synchronize your component with external systems.
That means things like:

  • network requests
  • WebSockets
  • timers
  • browser APIs
  • subscriptions
  • third-party libraries

If your effect isn’t interacting with something outside React, there’s a good chance you don’t need one.

1. Don’t Use useEffect For

One of the most common examples I still see is this:

const [fullName, setFullName]=useState("");
useEffect(() => {
    setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

Enter fullscreen mode Exit fullscreen mode

It works but React now renders twice. The process that now is doing is the following:
render –> effect runs –> state changes –> render again
and there’s no reason for that.

Instead i do this:

const fullName=`${firstName} ${lastName}`;

Enter fullscreen mode Exit fullscreen mode

2. Don’t Synchronize Props Into State

const [user, setUser] = useState(props.user);
useEffect(() => {
    setuser(props.user);
}, [props.user]);

Enter fullscreen mode Exit fullscreen mode

Most of the times this creates two sources of truth. Eventually one of them gets updated and the other doesn’t. Unless you intentionally want a local editable copy, just use the prop directly. It’s much simpler

function prodile({user}){
    return <h2>{user.name}</h2>;
}

Enter fullscreen mode Exit fullscreen mode

3. Don’t Calculate Values Inside an Effect

I’ve seen code like this many times.

const[filteredUsers, setFilteredUsers]=useStat([]);

useEffect(() => {
    setFilteredUsers(
        users.filter(user=> user.active)
    );
}, [users]);

Enter fullscreen mode Exit fullscreen mode

That’s unnecessary state, i’ts way better:

const filteredUsers=users.filter(
    user=> user.active
);

Enter fullscreen mode Exit fullscreen mode

If the computation is actually expensive:

const filteredUsers=useMemo(() => {
    return users.filter(user=> user.active):
}, [users]);

Enter fullscreen mode Exit fullscreen mode

Notice that useMemo is an optimization, not a replacement for every calculation.

4. Debugging Is One of The Few Places Where I Still Use Effects A Lot

When debugging state updates I often do this:

useEffect(() => {
    console.log(user);
}, [user]);

Enter fullscreen mode Exit fullscreen mode

It’s incredibly useful while debugging but before merging the code, delete it.

5. Fetching Data With useEffect Isn’t Always The Best Choice Anymore

Years ago almost every React project looked like this:

useEffect(() => {
    fetch("/api/users")
        .then(res=> res.json())
        .then(setUsers);
}, []);

Enter fullscreen mode Exit fullscreen mode

Nowadays we have much better alternatives. Libraries like TanStack Query or SWR solve things that you eventually end up building yourself:

  • caching
  • retries
  • background refetching
  • loading state
  • error state
  • deduplication And instead of all of this, you can:
const {data, isLoading}= useQuery({
    queryKey: ["users"]
    queryFn: getUsers
});

Enter fullscreen mode Exit fullscreen mode

That’s less code and you get fewer bugs and better developer experience.

If you’re interested in API reliability, I wrote another article about common integration mistakes:

“Building Reliable API integrations in Modern Web Applications”

6. Effects Often Hide Architecture Problems

Something I’ve noticed over time is whenever I find myself writing lots of effects indife the same component and it’s usually because the component is trying to do too much. For example:

  • fetching
  • filtering
  • sorting
  • formatting
  • validation
  • event handling
  • rendering

and everything together. Splitting responsabilities into smaller hooks or components ofter removes half of those effects automatically.

When You SHOULD Use useEffect

None of this means “never use useEffect”. There are plenty of legitimate use cases to use it, and let me tell some of them.
WebSocket connections:

useEffect(() => {
    const socket = new WebSocket(url);
    return() => socket.close();
}, []);

Enter fullscreen mode Exit fullscreen mode

Timers:

useEffect(() => {
    const id= setInterval(fetchData, 5000);
    return() => clearInterval(id);
}, []);

Enter fullscreen mode Exit fullscreen mode

Browser APIs:

useEffect(() => {
    window.addEventListener("resize", onResize);
    return() => {
        window.removeEventListener("resize", onResize);
    };
}, []);

Enter fullscreen mode Exit fullscreen mode

Third-party libraries:

useEffect(() => {
    const chart= new Chart(canvas);
    return()=> chart.destroy();
}, []);

Enter fullscreen mode Exit fullscreen mode

These are exactly the kinds of external systems effects were designed for.

My Personal Rule

Whenever I’m about to write an effect, I stop for a second and ask myself if am I synchronizing with an external system or am I compensating for my component design. That question alone has removed a surprising amount of unnecessary code from my projects.

Conclusion

useEffect isn’t bad. It’s just much easier to overuse than most React hooks. Today I try to use:

  • derived values instead of derived state
  • props instead of synchronized state
  • TanStack Query for server state
  • custom hooks for reusable logic
  • effects only when I actually need to synchronize with something outside React

And you can get fewer renders, less state, fewer bugs and components that are easier to understand months later.

Next Articles in This Series

Part 2: Stop Fetching Data Inside useEffect
Part 3: Stop Syncing Props Into State
Part 4: Event handlers are usually the better place for side effect
Part 5: Stop Using Effects for State Resets

Thanks for reading!! If you’re looking for help with an existing project or need someone to solve a tricky frontend/backend issue, you can also find my freelance profiles through my Dev.to profile.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다