Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Ahh, this is such a pet peeve of mine. I hate how it leaks. A thing I often also encounter in this vein is when you write a useEffect, but the linter forces you to declare everything in the dependency array. I only want the effect to trigger when x changes, and then call function y. But I have to declare y as well, but then if y isn't memoed it will trigger every render. But I don't want that, and I might not even have full control of function y, coming from somewhere else. I could usecallback around it myself first, but that just moves the problem, as I need to maintain the correct closure, or there will be subtle bugs.

A second but unrelated grief with hooks is when you get async updates happening in between renderers where you want to update some state and then do some logic. Let's say I'm waiting for 2 requests to finish. They both should update a value in my state. However, to not lose an update if both happens at the same time, I need to do the setState with a callback to see the latest value. But then, what if I want to trigger something when that new calculated state value is z? I can't do that imperatively inside the callback, and outside it I can't see the new value and don't know that I now should do something additional. I have to do it in a useEffect, but that decouples it too much, the logic belongs where I want to put it, in my state hook. Not in some useeffect wherever. The other option is to misuse refs to also maintain a current state there in addition to the useState. So always use the ref, but set the state in the end to trigger a re render.

Hooks are so unelegant for real problems. I hate how they force your hand to write spaghetti.



I might be an outlier here, but I really miss declaring component properties as actual object properties.

Components seem extremely similar to classic OO, why can't I use the same syntax.


React with hooks should have been a new framework. The only reason it wasn't was because of branding. It's an entirely different paradigm.


And it happened at the same that that learning React for 6 months was enough to get a job so very fast a good % of React developers were already using hooks (and actually never used React Components)


> Ahh, this is such a pet peeve of mine. I hate how it leaks. A thing I often also encounter in this vein is when you write a useEffect, but the linter forces you to declare everything in the dependency array. I only want the effect to trigger when x changes, and then call function y. But I have to declare y as well, but then if y isn't memoed it will trigger every render. But I don't want that, and I might not even have full control of function y, coming from somewhere else. I could usecallback around it myself first, but that just moves the problem, as I need to maintain the correct closure, or there will be subtle bugs.

If y never changes it should be declared as a const function outside of the context of the component, then it can be safely included in the dependency array without triggering unnecessary rerenders.

If y does change, you've just created a bug where your component will keep using an old version of y.


Yup, but that's the problem. I don't know, and I don't care, I just want to run my effect when x changes. But I can't, the details of y's implementation must leak.


Must it?

React is a closed ecosystem. Anything that enters either do through the root component or through hooks (in the functional version). If both x and y enters the ecosystem, they must adapt to the rules, meaning you write what happens when they change. Because the only reason for them to enter is that they are not constant outside React's world (which is the ultimate truth). If they are constant, then just use the reference directly.


Yes, but then you have to do as the author says: wrap every single function in a use callback and declare it dependencies. Otherwise it's unsafe to use for others. Which to me is a broken design. And y in my case may not be my function, either from a library or somewhere else in the application I don't want to modify just because my usage needs it. It should be a compiler thing, not up to the devs, the abstraction feels off.


I think you've got this backwards. If you write a React component that internally uses some 3rd party component/hook, and on every render of your component you pass something as a prop to that 3rd party component that's different from the previous render you should expect that 3rd party component/hook to also rerender/rerun. This isn't really surprising, nor is it even a problem in most cases.

If you're the one writing that reusable thing, you don't need to do anything special or write the kind of defensive code you're talking about. It's up to the original source of those props to make sure they're not creating new objects every render if they're in a context where that even matters


I don't mean I'm passing new stuff to the 3rd party hook, but that it returns a function that's usecallbacked, and hence I cannot myself use it as a dependency in a useEffect without it triggering every render. So yeah, if you expose a function in a piece of reusable code, you must useCallback around everything and be very defensive, or you mess up for those integrating with you.


Often I don't want to run effects, I just want everything calculated properly and then have my components render. I see useEffect() as a bad smell and keep score by how few of them I use (like golf) There really are cases you need it, but people often use them to move state around when they are keeping state in the wrong place.


useEffect should be used only when you want to bring something from outside the React tree which is not constant compared to the tree lifetime (anything that's not part of the UI module), hooking it to the tree lifecycle. useRef is for when you don't care the external thing's mutation. Any other hooks should be used when deriving from things that is already present in the React tree (props, local state, or other memoized variables)


y might be "changing" but being effectively the same function or the same array. There are legitimate cases when you want to just read the latest value of something inside an effect without it being a dependency, and after years of gaslighting about it React seems to agree and useEffectEvent is coming.


I use useEffect the same way and suffer the same grievances. I think it's because useEffect is intended as a way to keep references/state synced, not trigger downstream logic on various interactions. But there's only one useEffect, so it does all the things.


> The other option is to misuse refs to also maintain a current state there in addition to the useState. So always use the ref, but set the state in the end to trigger a re render.

Arugably this isn't a misuse, but just accepting that Reacts state management isn't powerful enough for what you need. Something akin to useRef + useSyncExternalStore is often what developers want.

For example, there's no guarantee that your useEffect will be invoked with the intermediate state you wanted to observe.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: