Live data from Hacker News

We memo all the things (2020)

attardi.org

61–70 of 84 posts

Re: We memo all the things (2020)

#62
post #6

This feels to me like another example of how the drive to use nothing but functional components in React is harming readability. Class based components were allowed to define a `shouldComponentUpdate` method which would be called ahead of rendering to decide whether a re-render is needed. Having the parent component memoise the component instead feels like a step backwards as we're now asking the parent to carry an u…

the parent doesn't have to memoise the component though. You can do this: export default React.memo(function myComponent(props) { // implementation }); though you would likely want to set displayName before exporting, in reality.

In which case, I stand corrected. I’ve not used React for a while and wasn’t aware that was possible.

Re: We memo all the things (2020)

#63
post #15

Earlier quoted context omitted.

I've always thought of "premature optimisation" as optimising something that's not your "hot path". If there's no clear hot path, everything is the hot path, and small optimisation gains everywhere are the only thing you're going to get. So at this point, it's not premature. You could also rewrite your code so that there is a clear hot path, but in that case it seems to be React rendering, that's optimised by using m…

The death from a thousand papercuts. I'm not terribly convinced with memoization though. You're using extra memory, so it's not free optimization. We have Redux memoized selectors everywhere. I can't help but wonder how much of that is actually a memory leak (i.e. it's never used more than once). Granted, components are a bit different. I always do cringe when I see a lint rule forcing you to use a spread operator in…

> I always do cringe when I see a lint rule forcing you to use a spread operator in an array reduce(). It's such a stupid self-inflicted way to turn an O(N) into an O(N^2) while adding GC memory pressure. All to serve some misguided dogma of immutability. I feel there is a need for a corollary to the "premature optimization is the root of all evil" rule.

I think a rule of "don't try to use X as if it was Y" would be reasonable. I love immutability, but the performance cost in JS is really high. Many people are fine with using Typescript to enforce types at compile time and not at runtime. Maybe many people would be fine with enforced immutability at compile time (Elm, Rescript, OCaml, ...) and not runtime?

Re: We memo all the things (2020)

#64
post #6

This feels to me like another example of how the drive to use nothing but functional components in React is harming readability. Class based components were allowed to define a `shouldComponentUpdate` method which would be called ahead of rendering to decide whether a re-render is needed. Having the parent component memoise the component instead feels like a step backwards as we're now asking the parent to carry an u…

the parent doesn't have to memoise the component though. You can do this: export default React.memo(function myComponent(props) { // implementation }); though you would likely want to set displayName before exporting, in reality.

But that is still memo-ing, just in a different part of the code. And I'm not sure wrapping all components in React.memo is a good practice, otherwise all components would be memo-ed by default. `shouldComponentUpdate` is more explicit

Re: We memo all the things (2020)

#65

Interesting, I mostly followed this approach which is to basically never use those constructs unless you are 100% certain you know what will happen. https://kentcdodds.com/blog/usememo-and-usecallback TLDR; > Specifically the cost for useCallback and useMemo are that you make the code more complex for your co-workers, you could make a mistake in the dependencies array, and you're potentially making performance worse…

The problem with avoiding useCallback is that another hook will bite you: useEffect. If you need to define functions that interact with your component's state, you have to memoize them with useCallback (or useRef) to avoid a useEffect infinite loop. What's even worse is that if functions passed as props are unstable, your useEffect will run every time the parent component renders — meaning that a component can't trus…

hooks in general are a huge footgun. You need to place them at the preamble of your function (and not nested). They have to be named with "use" prefix (worth mentioning is React basically commandeered the entire "use" namespace for their own purposes via lint enforcement, which will bite you in the ass eventually), and they are poorly designed.

Take useRef for example. You'd logically expect it to work with useEffect and that would be how you use refs in hooks land. But of course, refs are still a design wart on React (they've been through, what, 4 iterations now and they still can't figure out the interface?!). So of course you need to use useCallback. So what is the point of useRef then? I have no idea. The only use I've found is for "instance" variables. Or maybe onClick callbacks that run later. But now you have a ref that only works in some cases and not others. Yay, "composability"

Browse the React docs and you'll find the caveat-to-design ratio is exceedingly high. On any other project you'd assume this is beta or alpha ware.

Re: We memo all the things (2020)

#66

Earlier quoted context omitted.

The problem with avoiding useCallback is that another hook will bite you: useEffect. If you need to define functions that interact with your component's state, you have to memoize them with useCallback (or useRef) to avoid a useEffect infinite loop. What's even worse is that if functions passed as props are unstable, your useEffect will run every time the parent component renders — meaning that a component can't trus…

hooks in general are a huge footgun. You need to place them at the preamble of your function (and not nested). They have to be named with "use" prefix (worth mentioning is React basically commandeered the entire "use" namespace for their own purposes via lint enforcement, which will bite you in the ass eventually), and they are poorly designed. Take useRef for example. You'd logically expect it to work with useEffect…

useRef can be used to hold a reference to DOM elements, useful for breaking out of Reactland or to hold and mutate values that should not cause a rerender.

Re: We memo all the things (2020)

#67
From the useMemo docs: https://reactjs.org/docs/hooks-reference.html#usememo

You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance.

I think about this section a lot. If they actually changed useMemo to sometimes "forget" values, it would break so many useEffect dependency arrays (including my own).

Re: We memo all the things (2020)

#68
post #38

Earlier quoted context omitted.

the only time I find it to be required is when passing in callbacks to custom hooks with props that may change and you'll notice immediately because the callback will continuously run

If you're using React.useCallback to avoid triggering further hooks down the line, then you're using it wrong. Since React.useCallback is ostensibly just React.useMemo wrapped around a function, this note in the documentation is just as applicable: You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalcu…

I was following a pattern similar to react-table, where I'm destructuring a function off of a previous hook and passing it to another hook as a callback. This allows the 2nd hook to update state in the first, which causes it to infinite loop if the function isn't wrapped. I think this pattern is more complicated than it sounds, but really helps to remove business logic from a component

Re: We memo all the things (2020)

#69

Earlier quoted context omitted.

The problem with avoiding useCallback is that another hook will bite you: useEffect. If you need to define functions that interact with your component's state, you have to memoize them with useCallback (or useRef) to avoid a useEffect infinite loop. What's even worse is that if functions passed as props are unstable, your useEffect will run every time the parent component renders — meaning that a component can't trus…

I wouldn't say useEffect is a footgun, it just requires realising that React is doing shallow comparisons.

very good point

Re: We memo all the things (2020)

#70

I find the state of things in React, pun intended, a bit sad. Hooks are definitely an improvement over class based components but it still suffers from the same issue - having logic and state in the view layer leads to spaghetti code. Not to mention dependency arrays which are easy to get wrong and the weird syntax you end up with everywhere. I'm a big fan of MobX and it pains me to no end that it didn't took off bet…

This 100%. I still don't understand why React devs are so infatuated with colocating business logic with the UI that presents the result of that business logic. Sure, in the small (a todo list app? a weekend project?) it's probably a lot easier to reason about if you just jam everything into the same file. But why is it so difficult for people to see that the reason their large application is bloated, untestable, unm…

but hooks allow you to easily move business logic outside of your component. most business logic is simple so people use it inline. isolating it makes it pretty easy to test and reuse
Post reply on HN