r/reactjs 20h ago

Discussion What’s the real problem with useEffect in React?

Here is my honest question:

What's the actual problem with the useEffect hook? All over the X/twitter, I see a lot of negativity about this hook. It seems like a buggy thing in React.

My opinion is that developers blame useEffect because it's often used for data fetching as the primary use case. As we deal with various states like loading, data, error etc… synchronization of these causes bugs.

Also, a misunderstanding of the rendering cycle in React, such as where useEffect gets called could introduce additional misuses and bugs.

Hence, just saying useEffect is evil, may not be the right assumption is what I think. But, there could be cases that I'm missing.

What's your take or opinion about it?

46 Upvotes

94 comments sorted by

133

u/derHuschke 20h ago

If a mistake is easy to make by an inexperienced developer and somewhat hard to find by an experienced one, the library has a flaw in my opinion.

And i say that as someone who loves React. 

3

u/RedditNotFreeSpeech 11h ago

I also use react daily but for my personal stuff I've switched to solid and I love it.

6

u/atapas 20h ago

💯 agree

4

u/Kooky-Ad-295 15h ago

Still waiting for a flawless lib, easy to set up, learn, but very powerful, efficient and covering all use cases perfectly?

6

u/TemporarilyAwesome 11h ago

Svelte my friend

98

u/lIIllIIlllIIllIIl 20h ago edited 20h ago

useEffect is an escape hatch for handling side-effects and interact with the world outside of React. It's useful if you need to make an API request or interact with the DOM when a component renders.

The problem is people using useEffects to adjust states within React. State updates should be atomic. If a user action modifies a state, it should lead to another valid state. It should not lead to a partially valid state that only becomes valid after running a few useEffects. If a child components needs to adjust a state of a parent components, most likely the component hierarchy is wrong, and the state and logic should be moved around.

5

u/Shehzman 17h ago

What about a child notifying a parent and that notification leads to a state change? Isn’t that what passing callbacks as props are for?

21

u/lIIllIIlllIIllIIl 17h ago

A child updating a parent in a callback is fine, as long as it's the result of a user interaction (or any other external system) and happens in an event handler (i.e. onClick, onStorage, onAnimationEnd, etc.)

If the update happens in a useEffect of the child component and doesn't interact with an external system, most likely the parent component could've handled the update itself, or the update should've happened in another callback.

As long as you're not adjusting a state exclusively based on another state, it's good.

3

u/nickjvandyke 16h ago

Yes but usually this can and should be done where you update the effect-triggering state. You should call the prop callback directly instead.

3

u/Shehzman 16h ago

Right the parent still updates the state but in the callback method passed to the child.

3

u/Lower-Excuse-6558 12h ago edited 12h ago

OMG finally someone gets it. RTFM. React can also be combined with vanilla. Christ. I’ve been in front end too long. Do you guys not run garbage collection out performance checks or sequences of calls? You literally can re-create use effect yourself. Use the other effects for control as the op of this comment mentioned. Ui behavior OSS different than side effects and knowing how to propagate or use pub/sub. Use a light middleware. It’s an array of actionables. And people don’t understand true asynchronous actions. Stop fetching with use effect!! Ffs 🤦‍♂️

Man, I with people read designs and patterns in JavaScript. They just jump into an MVVP expecting to be full stack. Use nest, for api architecture. Next is just react with vercel controlling everything.

2

u/Hamburgerfatso 9h ago

I get it tho, that explanation doesnt mean a lot to someone new to react. Its hard to understand what an escape hatch is if you have no experience or knowledge about the scope of what the hatch is escaping from (hence being new to something). The concept of useeffect's "run this stuff when that value changes" is the most intuituve feature for a noob to latch onto.

77

u/binocular_gems 20h ago

It's like `type: any` to me. There's nothing inherently wrong with it when used sparingly and properly, but developers often fall back to it when they shouldn't, and it can lead to a cascade of complexity. That said, programming communities on social media (way back to the ancient days of usenet, BBS, and *groups) tend to over-inflate problems and get dogmatic about it.

12

u/Ellsass 20h ago

Exactly. It’s a longterm maintenance issues and a huge source of difficult-to-find bugs.

27

u/musical_bear 20h ago

I actually don’t think typing something as “any” is ever appropriate. useEffect has a handful of valid use cases where only it can be used to solve a problem. Typing something as “any” in TS is purely a lazy hack. It’s a “I don’t feel like thinking through this, so I’ll just turn off type checking completely.” I cannot think of a situation in TS where you’d “have” to use “any” to solve a problem, or even where it would be a viable best course of action for a problem.

11

u/woahwhatamidoing 19h ago

Best reason I got: dealing major/large 3rd party library that doesn’t publish typescript definitions for their package. Usually don’t have time to go write & maintain those ourselves because sometimes (especially ones written in vanilla js) can get stupid complex to type properly.

Sure, you can call this lazy since it still would be better to do types for it, but for a small team that’s not always realistic.

11

u/marcagba 19h ago

Even in this you could consider using unknown rather than any, but YMMV

3

u/Karpizzle23 16h ago

You should use unknown and have shims of types. any is banned across many different eslint configs for a reason, and that's because it essentially just turns off typescript.

If the code doesn't have access to a type, use unknown, that's the semantically correct usage and forces you to check for properties in the code using 'in' or hasOwnProperty etc (or Zod)

3

u/LatvianCake 18h ago

I find myself using any when trying to narrow down an unknown type. Checking deeply nested properties on an unknown object is a pain in the ass.

Another common one is dealing with broken types from libraries you don't control. Or writing tests where creating the full type is too complicated and has no benefits.

2

u/oldestbookinthetrick 16h ago

Checking deeply nested properties on an unknown object is a pain in the ass.

So type it as something better than unknown with optional or nullable properties? You must know what properties it has or might not have, as you're accessing them in the runtime code.

any is poison to a codebase because not only is it a "I don't care about types here" escape hatch, it also means that anywhere you pass that type also accepts it. That any type has a hall pass to be used anywhere in your codebase. Other code that might have otherwise been type safe, now silently isn't because you passed any into a function or component somewhere.

2

u/LatvianCake 15h ago

So type it as something better than unknown with optional or nullable properties? You must know what properties it has or might not have, as you're accessing them in the runtime code.

It's unknown because you don't know what type it is. That's the entire point. You navigate its properties to find out what type it could be so you can potentially narrow it down.

1

u/oldestbookinthetrick 15h ago

Can you give an example of what you mean?

1

u/LatvianCake 14h ago

Anything involving unknown data. A caught error, an API response, user input, file contents, deserialized data etc.

Its type is unknown because it's arbitrary or unknown data. So you write a type guard or inline casting logic that tests if this unknown object has certain properties with certain values. For example to detect known error responses, a type that we are expecting, etc. And sometimes the easiest way to do this kind of reflection is by casting it to any.

You can use in but it only works in basic scenarios. If you have nested properties, it becomes bulky very quick. `instanceof` works only in very limited scenarios.

Libraries like zod can be helpful but it depends on the usecase. In some cases a check with any is a one-liner that's understood by everyone, while the Zod version is a 10-liner that confuses some of your team. Not to talk shit about Zod because it's an amazing library but it's not always the right tool for the job.

1

u/oldestbookinthetrick 13h ago

So you're doing like

const couldBeAnything: = (getSomeStuff() as any)

const stuffIWant: StuffIWant = couldBeAnything?.stuff?.i?.want

?

Seems reasonable if so, lot of lines of in otherwise... If you also runtime check the type of .want

1

u/LatvianCake 2h ago

Kinda, it usually looks something like this:

const getApiResponse = (): unknown => { ... }

const isAuthError = (data: unknown): data is AuthErrorResponse => 
  (data as any)?.response?.errors?.firstError?.errorCode === "AuthError"

const response = getApiResponse();

if(isAuthError(response)) {
  // handle error
}

1

u/oldestbookinthetrick 2h ago

Nice, yeah that makes sense

27

u/creaturefeature16 20h ago

I've always understood it to be an "escape hatch" from React's rendering cycle, which is great for fetching data, but not so great for many other purposes and is used to "get around" the issues that re-renders bring, instead of attempting to understand the mechanics of why the re-rendering is happening in the first place, and composing the components properly.

I've related it to using !important in CSS: it's absolutely clutch for certain situations, but it otherwise complicates the overall code, bucks the natural order of things (in CSS' case, specificity) and makes debugging harder if you lean on it too much.

10

u/atapas 20h ago

The !important analogy is a good one

3

u/slashp 19h ago

Cascading for a reason...

22

u/jackster31415 20h ago

Really not much to say other than the excellent docs page: https://react.dev/learn/you-might-not-need-an-effect

13

u/nabrok 20h ago

A key part of that sentence is might not. Somehow a lot of people seem to read that as never.

6

u/jackster31415 20h ago

Yeah I mean, that’s a skill issue. Of course it has its uses, otherwise it wouldn’t exist. I do believe the docs provide great examples on why you may need it and many cases where you don’t

6

u/nabrok 20h ago

I agree. When I first read that article I thought "okay, I know all this" but then I look over some code I wrote when hooks were new and realize "oh shit, I did the thing I'm not supposed to".

So, good thing that article exists to highlight some of the pitfalls.

0

u/the-forty-second 18h ago

I agree about the skill issue, but I don’t think its existence is proof of its utility. It is quite possible to add something to a library, discover it is a mistake but not be able to remove it because a bunch of code relies on it.

9

u/ColonelGrognard 18h ago

It should be called misUseEffect.

Seriously though, there is nothing inherently wrong with it, it's an operator/dev problem.

2

u/atapas 18h ago

Name justified

6

u/ClideLennon 20h ago

It's one of the main features of React. It's not a bug. It is often used when one does not need to use it. If you don't need to use it and you do use it, it creates unnecessary complexity in your app that can get out of hand if you let it. There is a very good guild for this:

https://react.dev/learn/you-might-not-need-an-effect

3

u/stefanskipiotr 19h ago

It makes code more complicated. People often forget they can just use event handlers and react to property changes instead. It's harder to debug and unnecessary in most cases. Using it as a "run on mount" hook with an empty dependency array is especially unclear — it's just bad design.

The funny part is that I've noticed AI reaches for it a lot. It learned the wrong lessons ;)

1

u/KrisSlort 3h ago

Because it learns from other code rather than parsing and undersranding docs. So if the majority of people use it wrong, AI learns that.

3

u/pm_me_yer_big__tits 19h ago

There's nothing inherently wrong with it as long as you know how to use it. People who say it's 'evil' clearly don't.

7

u/SchartHaakon 20h ago

No one is saying useEffect is evil, as far as I've seen? It's just a footgun. That's it. There are a few very valid use cases for it, and a shit ton of ways to misuse it and cause excessive rendering while technically maybe achieving what you wanted to achieve.

I'm not sure I get the question you're really asking because the question assumes people think the hook itself is badly written or something. It's not, it's just misused.

1

u/atapas 20h ago

Saw someone post this on X

“React is solved, useEffect is not”

It also got attention from others on similar lines. It gives the wrong message to junior developers in my opinion. My question was based on these.

6

u/Antti5 19h ago

Respectully: Fuck X or whatever it's called today.

Also fuck the kind of "discussion" where everything needs to be a punchline and nuance is perceived to be too complex for the reader. Fuck all of that.

useEffect has it's uses, however it's also undeniably over-used. React's own documentation is all you need on this subject.

1

u/KrisSlort 3h ago

Using X is your problem then. That place is a cesspit. The shortform approach misses all nuance and encourages ragebait.

2

u/brandonscript 20h ago

Like anything in software, the problems are one of:

  • ignorance
  • opinions
  • othering

This one's just ignorance. If you know how to use it and what not to do, it's incredibly powerful.

2

u/some-random-guy-2026 19h ago

useEffect is a necessary part of react. That being said, it is also the source of tons of hard to diagnose bugs and makes code harder to reason about because you cannot easily trace the flow of changes from one method to the next. Basically is a like completely async event system that responds to a change in component A all the way down in component Q and you don't even see that is possible when you're making the change in A.

This is why it should be used sparingly. The ultimate anti pattern being calling setState from within a useEffect

2

u/SendMeYourQuestions 19h ago

It turns an already complicated state machine into one with unnecessary additional states and state transitions.

2

u/BoBoBearDev 8h ago edited 8h ago

It is like C++, every time they told me it is easy and they can do it, they fucked it up and expect me to clean up their mess.

Even if they did it perfectly, it is like a jenga. Someone else touched it and it collapsed.

4

u/iareprogrammer 20h ago

Pretty much all the reasons you listed. The problem is too many people don’t know the proper way to use it

2

u/neon_hive 20h ago

UseEffect is a footgun because developers use it to derive state instead of computing values during render. Synchronizing state with effects creates redundant renders and tearing that breaks the rendering model.

1

u/xchi_senpai 20h ago

Its the misuse of dependency array

1

u/sylvant_ph 19h ago

I guess it's a combination of couple of things - adding additional boilerplate, an extra render to run stuff, not optional/conditional. I just wanna make a request, get my data and render the component using that data (or do something else if request fails). To achieve this you need to overengineer stuff. And if you add couple more business rules to the logic, it goes out of hand and you might end up stacking couple effects and complex codependency.

1

u/darthexpulse 19h ago

Hard to track down, it needs to be where it is expected to be and documented properly.

1

u/octocode 19h ago

it’s a tool built with a single simple purpose that people abuse to do literally everything.

1

u/raaaahman 19h ago
  1. Listen to people who say to not use useEffect
  2. Use the library recommended by such people
  3. Look inside the library's source code
  4. It's useEffect all along

When you understand that useEffect is a way to skip calls to an external system, it becomes smoother. (If you can afford calling to the external system every time your component re-renders, then you indeed don't need useEffect).

2

u/prehensilemullet 17h ago

When you understand that useEffect is a way to skip calls to an external system

It sounds like you're implying that you would just call the external system directly from the render method if you have no need to skip. I can't say for sure, but I believe that's likely to cause race conditions, at least with concurrent features like Suspense and transitions. The point of useEffect is also to call external system at the proper time, which is not in the middle of rendering, but after the rendering has committed.

This may have been more of a concern with their initial plans for concurrent mode that they ended up changing. But I'm almost certain that if anything you call during render ends up synchronously causing another component to update, it will error out, whereas code in useEffect is allowed to do that.

1

u/raaaahman 3h ago

The point of useEffect is also to call external system at the proper time, which is not in the middle of rendering, but after the rendering has committed.

Ah yes, that's an oversight on my part. useEffect are applied during the commit stage, not the render stage.

It becomes of use when you start using useRef with DOM nodes, which should not be accessed during render stages (because they could not exist yet).

0

u/marta_bach 19h ago

Of course the library gonna use useEffect, what they meant is to not use useEffect yourself especially directly in the component.

The only time you need useEffect is when it's tightly coupled with the other hooks like useState, and becase of that it's always better to make it as a custom hook so the logic is containerized. Most of the time those custom hooks is already created by someone and using the existing popular library is the right call for that, unless it's super simple like a simple debounced state hook.

1

u/LiveRhubarb43 19h ago

There's nothing wrong with it. It's great for data fetching. There's a lot of people who don't understand how it works or what it's actually for, and they'll hold up examples of devs using it incorrectly as examples of why we shouldn't use it.

A lot of people will say to use a query library instead - and I agree with them - but those libraries are using useeffect or something like it under the hood anyways.

1

u/Arsenicro 19h ago

The problem with useEffect is that it is extremely easy to misuse. And it is not only a theory; it is a fact that it has historically been misused. People don't understand what useEffect does, how it works, or when to use it. You can find multiple posts that recommend "solutions" with useEffect, which may lead to new problems. AI learned from those posts. People learned from those posts. When the problem you want to solve seems solved by using useEffect, you may not even consider that this is wrong.

It is evil because it has a history of misuse, making it easy for new people to find such misuses and assume it is the correct way to use it. It is also evil because this misuse is hard to notice, especially if you are new to React, since it seems to solve the problem at hand. It almost encourages you to use it to, for example, synchronize some internal states in React. And even if you know what useEffect does and when it is supposed to be used, it is still easy to do something wrong and, for example, forget to add a cleanup function, which may lead to issues (like using useEffect to load data with a simple query search, which may, without a cleanup function, lead to inconsistencies between the search query and loaded data).

It is a pretty bad hook overall, and I always prefer avoiding it when I can.

1

u/OHotDawnThisIsMyJawn 19h ago

My opinion is that developers blame useEffect because it's often used for data fetching as the primary use case. As we deal with various states like loading, data, error etc… synchronization of these causes bugs.

If this was the only thing people used useEffect for, there would be no problem.

The issue is using it for literally anything besides syncing with an external system, and that's where all the problems are.

1

u/wolvar__ 19h ago

Para mi es una manera de controlar el render y re-render en cascada de ReactJS, la verdad no se que uso le están dando si bien es cierto existe el callback-hell donde es cuando hacen demasiadas condiciones dentro de un useEffect se vuelve ilegible todo enredado y recomendaria mejor usar el hook useEffect por separados.

1

u/SangSuantak 19h ago

I was given a task to add a new input field in a master form. You'd think it's a piece of cake, but no. Useefect was used so badly in the component it was difficult to track what's causing the form values to change. I knew it's going to be a maintenance nightmare, so i re-wrote the whole component for my own sanity. Luckily it wasn't a big form.

1

u/carbon_dry 19h ago

I don't have an opinion on it. I just read the docs. The docs are a good place to answer this rather than X/Twitter.

useEffect is for syncing with external events, mostly. Most other uses of it will be improper, all though there my be legit uses for it inside react that takes skill to know. But reaching for an effect is not the default answer.

Have a read of https://react.dev/learn/you-might-not-need-an-effect which supports your concerns.

1

u/thesonglessbird 19h ago

I think a lot of it comes down the its name. If it was called something like “useSideEffect”, in the context of React components being pure functions, it would signal its intended use case better I think.

1

u/react_dev 19h ago

It does exactly what it needs to do. React needs to interact with external systems like the browser, backend and based on the state changes there, it needs to reconcile internal state. Because they’re external systems we need to do a side effect, thus use effect.

It’s hated on because often times you look at the dependency array of the useEffect and its props, states, local declared stuff that’s obviously not external systems. In those cases there must be a gap in the code. No questions asked.

1

u/jibbit 19h ago

Man, what a cop-out these answers are.

Programmer wants a lifecycle hook but gets a sync-machine. You think “run on mount” / “run when X changes” but you have to encode that as a deps array and hope it matches your intent. Experienced devs get deps arrays wrong constantly. thats a Leaky abstraction, not a skill issue

One hook, four jobs. Sync, reacting to changes, setup, derived state, all crammed into the same shape.

Timing’s invisible. Can’t tell from the call site if it’s before/after paint, every render, or interleaved with other effects.

Attracts its own worst use case: derived state. the one everyone agrees is wrong.

1

u/lightfarming 18h ago

useEffect creates side effects for state changes. so someone might be following the logic in the code, thinking changing a specific state is fine, while it actually triggers some unknown thing somewhere else in the code.

people often use it for things it isn’t necessary for, due to not being adept at react, and when it is everywhere it starts to make overly complicated code that is hard to maintain.

it should only be used for effects (interacting with things that are outside of the control of react)

1

u/AlexDjangoX 18h ago

Misused. Used for fetching initial page data.

useEffect(() => { getPodcasts().then(setPodcasts); }, []);

1

u/LancelotLac 18h ago

If it was only used for async data fetching it would be fine even though react-query is a better pattern. The issue is that people use it to synchronize useStates and all other bad stuff you shouldn't do.

1

u/atrtde 17h ago

because most people use it to synchronize state when it should be used to synchronize external system with React

1

u/averagebensimmons 17h ago

it's about using the correct tool for the job. when people start using React they over use the useEffect. I was certainly guilty of this too.

1

u/damdeez 17h ago

Although I love functional React I sure do miss class components and how easy it was to reason through the React lifecycle

1

u/prcodes 17h ago

Typically overused when there are simpler solutions https://react.dev/learn/you-might-not-need-an-effect

1

u/HomemadeBananas 16h ago

It’s not always bad, but way over used. Data fetching, yeah most cases better to use react query or something else outside of the component to handle it. But that’s the least offensive of ways you probably shouldn’t use it.

People use it for making some state change when some different state changes, etc. It’s just overused in a way that makes code worse and more confusing when most of the time you don’t need it.

Then it’s such a common code smell that AI gets trained on it, and AI also does this common mistake too, and you need to tell it to not do that, and some devs don’t know any better or don’t catch it, so reviewing the code I’m still constantly telling people don’t use useEffect here.

1

u/azangru 16h ago edited 15h ago

What's the actual problem with the useEffect hook? All over the X/twitter, I see a lot of negativity about this hook. It seems like a buggy thing in React.

I think this negativity is silly.

There must be an api that lets you say "here's some work I need you to do apart from rendering". All component libraries have this: lifecycle hooks in old react / angular / lit; effect in solid; probably something similar in svelte. It's just that react's useEffect's api turned out to be silly; and the double call in strict mode doesn't help any.

P.S.: I've just learnt that Ember doesn't have effects.

1

u/the_real_some_guy 15h ago

When code is written linearly, press button > do A > do B, the code is easy to follow, review, and change. If you move “do B” into a useEffect, the next person that edits that code might not notice “do B” is happening and then you get bugs. 

Many of the bugs I need to fix end up being in an useEffect. Most of the time, that code did not need to be in a useEffect. There are times when it’s the right tool, but most of the time it is not. 

1

u/Canenald 15h ago

There's a long-lived fallacy that when you are using a framework, you have to use only the APIs the framework exposes for everything, or you are using it wrong. If you pick a plain construct in the language you are working in, you're doing it wrong. This is, of course, not true, but it causes people to use React state when a plain variable will suffice, and an effect when simply setting the state or assigning to a variable works just fine.

React team and the community have been trying to fight it, but to no avail. We still get posts like this. We still run into overuse of effects when we onboard to new projects. Good thing we can use AI these days to just refactor all the mess.

1

u/abopabopabop 14h ago

The only problem is noob engineers overuse it

1

u/yardeni 12h ago

It's just easy to get wrong. Often people misuse it for selecting from data instead of memoizing, or forget ro cleanup after effects, or use partial dependencies. Its a powerful Model but you gotta learn it to use it right

1

u/bestjaegerpilot 12h ago

1) dependency arrays are really easy to break

2) it's used as an event system but because it changes any time a dependency changes, an effect can fire in surprising ways, leading to bugs

3) if you look at the official docs, the devs pretty much say that hooks are foot guns---"you may not need an effect"

1

u/Several_Bread_3032 9h ago

It’s overpowered for peeps who don’t understand it . I use to have it changing states everywhere waiting for other effects to take place . Just sloppy 💩 all around from my end with it when I tried Web development haha

1

u/Franks2000inchTV 6h ago

It’s fine, people just use it wrong in ways that cause a ton of problems.

1

u/minimuscleR 5h ago

I mean if you have a good router, and use Tanstack Query, and a form library, you will hardly ever use an effect? I've written maybe 4 or 5 in the last year? Thats as a professional software engineer working in react all day every day.

1

u/BlacksmithNo1687 3h ago

People use it when they usually just need to lift stats up. Typically, if you’re setting state within a useEffect and that useEffect has a dependency on state you’re using it wrong. Almost every time I review a pr with the hook, it’s used incorrectly

1

u/repeating_bears 20h ago

If there is an inherent problem with it at all, it's not about what it does, but that something about its design leads people to overuse it when it's not appropriate. I'd say that the name isn't great, but I don't have a better suggestion and naming things is hard.

1

u/cult0cage 20h ago

As others have said, it's mostly problematic because of peoples misuse of it. If it was truly an issue I'm sure the React team would deprecate it and offer a migration guide for existing codebases to follow.

0

u/christfrost 20h ago

It’s a fantastic hook, but 99% of developers are bad and thus they have no idea how to properly utilize it. And thus, if you don’t know how to use it, it messes up your application really bad and really fast.

0

u/NotGoodSoftwareMaker 20h ago

Its an easy way to get unbound behaviour without any good way to control or limit that behaviour

0

u/gnudle 19h ago

Love useEffect especially to let component fetch its own data. Rarely a problem even in a complex app with hundreds of files and tens of thousands lines of code

0

u/sporbywg 19h ago

Introducing a team of young developers to React, I would not use any other tool then useEffect