[HN Gopher] We memo all the things (2020)
___________________________________________________________________
We memo all the things (2020)
Author : davecardwell
Score : 106 points
Date : 2021-10-25 13:18 UTC (9 hours ago)
(HTM) web link (attardi.org)
(TXT) w3m dump (attardi.org)
| andkon wrote:
| Dumb question, but is there an equivalent concern for Vue? Or a
| reason why this kinda checking isn't necessary there?
| vlunkr wrote:
| > If you've ever profiled a React app - even in production mode -
| you know there is a non-negligible performance impact to every
| component that renders.
|
| Maybe it's just me, but I've used React for ~5 years and I've
| never needed to profile an app, since the performance out of the
| box has always been good enough.
| jbaudanza wrote:
| The situation is much more severe with react-native, which
| doesn't have a JIT compiler available.
| kecupochren wrote:
| 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 better. It's a godsend from like 5 years ago and it
| makes so many of these React pain points disappear.
|
| Instead of adding state to your components here and there, it
| works outside of the view layer. You define the model, derived
| computed views, actions and then just use it inside your
| components. You never ever worry about performance because MobX
| knows what is used where and it will optimize your renders
| automatically.
|
| Moreover, dealing with state outside of the view layer makes it
| much more easier to refactor, reason about and test your app.
| Sure, you can do the same with Redux but it's 10x more code.
|
| I recommend this article on this topic by the author -
| https://michel.codes/blogs/ui-as-an-afterthought
| brundolf wrote:
| I +1 MobX wherever I see it mentioned, but I have to disagree
| here:
|
| > having logic and state in the view layer leads to spaghetti
| code
|
| Sometimes it makes sense to put logic and state in your view
| components, and the wonderful thing about MobX is that it
| doesn't care. It lets you freely move your state around to
| wherever you want it to live: inside components, outside
| components, in a module-scoped object, in a global store, all
| of the above. It's just JavaScript objects.
|
| For those fighting with hooks: one of the best things about
| MobX is that it does all dependency-tracking (for effects, but
| also for components) automatically and flawlessly. An entire
| problem-space that's usually easy to mess up just vanishes in
| front of your eyes. Going back to anything else feels like
| going back to the dark ages.
| kecupochren wrote:
| > Sometimes it makes sense to put logic and state in your
| view components
|
| Of course, I do that a lot with generic, reusable components.
| Once I know it's too complex I extract it to model that gets
| passed through props. Win/win
| morgancmartin wrote:
| I'm not familiar with MobX, but I am a big fan of Jotai
| (https://jotai.pmnd.rs/). It is a spiritual offshoot of
| Facebook's experimental(?) Recoil library.
|
| It is a bottom up approach to state. Everything is modeled as
| atoms. Atoms can be defined in any module and are accessed by
| simply exporting/importing from/to the module. Simply call
| the useAtom hook and you're now using that state atom.
|
| Under the covers it is scoped via a top-level React context,
| I believe.
|
| Atom derivation, read/write, async, it's all there. It also
| hooks into a lot of other popular state libs like redux,
| XState, Zustand and many others.
|
| I much prefer it to Redux because there is zero boilerplate
| and extremely flexible. It can be easy to hang yourself with
| all the extra rope it gives you if you aren't careful though.
| notpachet wrote:
| 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,
| unmaintainable, etc is directly due to the blatant violation of
| separation of concerns that they're parroting?
|
| I feel like part of this is due to some devil's bargain on the
| part of the React maintainers. They want mindshare, and they
| know that it's easier to gain mindshare if the behaviour of the
| app appears simpler, and that appearance of simpler is easier
| to achieve if the behaviour is relegated to a smaller number of
| files...
| nfRfqX5n wrote:
| 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
| notpachet wrote:
| That's true. But to echo the underlying theme of the
| original blog post, it is difficult to ensure that a large
| team of developers (of varying skill levels) maintains a
| consistent approach to this. Different developers likely
| have different opinions of where that "simple" threshold is
| that warrants factoring out the business logic. And, when
| the push of a deadline comes to shove, it is tempting to
| just throw all the shit in the component with the promise
| that we'll refactor it at a later date.
|
| More fundamentally, I feel like putting business logic
| hooks in a component (even simple ones) sacrifices the
| cleanliness of components as simple stream transformers:
| input some scalar props, output some HTML. As soon as you
| start calling hooks within a function component, it's no
| longer purely functional. You have side effects. And those
| side effects result in a component that's trickier to debug
| and trickier to test.
| senand wrote:
| This should have ,,React:" mentioned in the title.
|
| I was thinking about a technique to write things down...
| nop_slide wrote:
| 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 by invoking the built-in hooks and preventing
| dependencies and memoized values from being garbage collected.
| Those are all fine costs to incur if you get the performance
| benefits necessary, but it's best to measure first.
| jakelazaroff wrote:
| 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 trust
| functions passed into it.
|
| This is one of many reasons I think useEffect is a huge
| footgun, and I really wish we had a better primitive for
| causing side effects.
| antihero wrote:
| I wouldn't say useEffect is a footgun, it just requires
| realising that React is doing shallow comparisons.
| nfRfqX5n wrote:
| very good point
| deckard1 wrote:
| 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.
| gherkinnn wrote:
| 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.
| antihero wrote:
| > you could make a mistake in the dependencies array,
|
| This is an auto-fix with eslint, and when it isn't exactly
| right (you need a "one way update") you can override that rule.
|
| I would posit that passing a value that is regenerated every
| render (as opposed to when it actually changes) outside of the
| component (via props or context) is much more dangerous and
| likely to create infinite loops. For stuff that stays internal,
| sure, knock yourself out (until it is required by a useEffect
| or anything else that needs dependencies).
| jasonkillian wrote:
| This is a great article and I agree with it fully.
|
| The argument that a lot of popular React voices have made, "React
| is fast and it's prematurely optimizing to worry about memoizing
| things until a profile shows you need it", has never rung true
| with me. First and foremost, there's a huge time cost to figuring
| out what those exact spots that need optimization are, and
| there's also an educational cost with teaching less experienced
| engineers how to correctly identify and reason about those
| locations.
|
| There are only two reasonable arguments for not using `memo`,
| `useMemo`, and `useCallback`. The first is that it decreases devx
| and makes the code less readable. This one is true, but it's a
| very small cost to pay and clearly not the most important thing
| at stake as it's only a slight net effect. The second argument is
| that the runtime cost of using these constructs is too high. As
| far as I can tell, nobody has ever done a profile showing that
| the runtime cost is significant at all, and the burden of proof
| lies with those claiming the runtime overhead is significant
| because it doesn't appear that it is typically when profiling an
| app.
|
| So, given that the two possible reasons for avoiding `memo`,
| `useMemo`, and `useCallback` are not convincing, and the possible
| downsides for not using them are fairly large, I find it best to
| recommend to engineering teams to just use them consistently
| everywhere by default.
| Zababa wrote:
| 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 memo and avoiding it completely.
| wpietri wrote:
| How could you not have a hot path? You're saying that you've
| measured actual usage and discovered that each thing happens
| to be called exactly the same number of times? That strikes
| me as extraordinarily improbable.
| Zababa wrote:
| That's not exactly it. It's more of a "If you have nothing
| that takes more than 1% of your resources, no single
| optimisation can get you more than a 1% reduction in your
| resources". That seem to be how most web apps are: you
| parse a little bit of HTTP, a little bit of JSON, you
| validate a few things, you call the database, that does a
| few things too, you have a bit of business logic, you call
| the database again, then have a bit of glue code here and
| there, and finally respond to the user with a little bit of
| HTTP and maybe some HTML, maybe some JSON.
|
| If that's how your app works and nothing can be optimised
| significantly, that's usually here where you can make big
| gains in performance by changing a big thing. One of these
| big things might be to put a cache in front of it, because
| a cache hit will be way faster than responding again to the
| same request. Another could be to change language. For
| example, from Python to Go. Since Go is (most of the time)
| a bit faster on everything, you end up being faster
| everywhere. Or even from Python to PyPy, a faster
| implementation. Another could be redesigning your program
| so that you have one single obvious hot path, and then
| optimising that.
|
| That seem to be the case for them here: no component is
| taking all of the resources, but by using memo everywhere,
| all of them take less resources, which leads to a good
| reduction of resources in general.
| deckard1 wrote:
| 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 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.
| Zababa wrote:
| > 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?
| napsterbr wrote:
| > has never rung true with me.
|
| Yeah, me neither. I'm seeing first-hand a "large" (but probably
| not Coinbase-large) webapp dying by 10 thousand cuts.
|
| The "you shouldn't care if it rerenders" components are,
| together, affecting performance. Going back and memoizing
| everything would be a nightmare and not a viable business
| solution. Rewrite everything from scratch is also not viable.
| So we have to live with a sluggish app.
|
| At the same time, memoizing everything does make your code
| unreadable.
|
| Honestly, it's a mess. I only accept working with this kind of
| stuff because I'm very well paid for it.
|
| On my personal projects I stay far away from the Javascript
| ecosystem, and it's a bless. Working with Elm or Clojurescript
| is a world of difference.
|
| Clojurescript's reframe, by the way, uses React (via Reagent)
| and something somewhat similar to Redux, without having any of
| the pitfalls of modern JS/React.
|
| I can write a large application and ensure that there are no
| unnecessary rerenders, without sacrificing readability and
| mental bandwidth by having to memorize everything.
|
| The conclusion I have, which is personal (YMMV) and based on my
| own experience, is that modern JS development is fundamentally
| flawed.
|
| Apologies for the rant.
| wpietri wrote:
| It seems to me you're being pretty breezy about readability. At
| most places, developer time is by far the most expensive
| commodity, and the limiting factor in creating more user value.
|
| In particular, bad readability is one of the sources of a
| vicious circle where normalization of deviance [1] leads to a
| gradual worsening of the code and a gradual increase in
| developer willingness to write around problems rather than
| clean the up. Over time, this death by a thousand cuts leads to
| the need for a complete rewrite, because that's easier than
| unsnarling things.
|
| For throwaway code, I of course don't care about readability at
| all. But for systems that we are trying to sustain over time,
| I'm suspicious of anything that nudges us toward that vortex.
|
| [1] https://en.wikipedia.org/wiki/Normalization_of_deviance
| jasonkillian wrote:
| I don't disagree with you on readability being important or
| on the value of developer time. It's just that the marginal
| costs of `memo`, `useMemo`, and `useCallback` are quite low.
| They don't add cyclomatic complexity, they don't increase
| coupling, they can be added to code essentially mechanically
| and don't carry a large cognitive overhead to figure out how
| to use, etc.
|
| The main downsides are that they take slightly longer to type
| and slightly decrease the succinctness of the code. And then
| there are a few React-specific complexities they add
| (maintaining the deps arrays and being sure not to use them
| conditionally) but these should be checked by lint rules to
| relieve developer cognitive load.
|
| Of course I'd rather not have these downsides, but in the
| end, it's still much less developer overhead than having to
| constantly profile a large application to try and figure out
| the trouble spots and correctly test and fix them post-hoc.
| And it means users are much more likely to get an application
| that feels snappier, doesn't drain as much battery, and just
| provides a more pleasant experience overall, which is worth
| it imo.
| lawwantsin17 wrote:
| I like that in the end he compared React to a virus that's
| ruining lives and it's solution to a universal mandate. I've got
| one for you. Don't use React with static content.
| eatonphil wrote:
| I like React a lot and have used it professionally for more than
| 5 years. First off I mostly haven't needed to memoize any time I
| can remember in any enterprise (non-SaaS) production or personal
| apps. But surely CoinBase is at a bigger scale than my apps
| were/are.
|
| But if it's the case that memoizing is such a good thing to do
| despite the effort (and I'm not debating that in this question),
| why is React designed in a way that requires you to opt into it
| and write the same boilerplate all over the place?
|
| If hooks make this a problem maybe hooks aren't the best (or at
| least pinnacle) design? (And I really prefer hooks, personally.)
| nfRfqX5n wrote:
| 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
| jdjb wrote:
| 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 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.
| acsreedharreddy wrote:
| If we have a component <ProfilePage id={id}
| onLoad={handleOnLoad} /> and inside profile page we use an
| effect to load from id and call handleOnLoad with the
| loaded profile data, then we need to put handleOnLoad in
| the useEffect dependencies. So we have to pass a callback
| wrapped in useCallback else the effect would fire every
| time ProfilePage rerenders.
| TheCoelacanth wrote:
| You're only using it wrong if you're trying to avoid
| triggering hooks as something other than a performance
| optimization.
|
| For example, something like this should work correctly even
| without useCallback, but you would be constantly re-
| subscribing for no good reason. const
| callback = useCallback(...); useEffect(() => {
| const unsubscribe = subscribe(callback); return
| () => unsubscribe(); }, [callback]);
| nfRfqX5n wrote:
| 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
| marcellus23 wrote:
| yeah, I was thinking about this too as someone who's not super
| familiar with React -- why isn't memoing the default behavior?
| Zababa wrote:
| I think that's because everyone needs to debug their React
| app, but not everyone needs the performance. So you optimise
| for the most common use case, where you make debugging
| easier. Memoization is a form of caching, caching is hard.
| Most backend web frameworks don't come with a cache by
| default, you add one when you need the performance. It's the
| same here.
| fouric wrote:
| What does "needed" mean in "I mostly haven't needed to memoize
| any time I can remember"?
|
| Does it mean that that your manager/team lead has never asked
| you to? Or that your production builds always hit some
| performance benchmark? Or that your _development_ builds hit
| that benchmark? Or that you never noticed a qualitative
| slowdown in your development environment? Or something else?
|
| "Needed" is a word you gotta define when you start talking
| about performance, unlike discussing functional correctness.
| eatonphil wrote:
| There was never a slowness in the apps I've worked on that
| came down to requiring memoization in React versus other
| basic things like doing pagination or other ways of rendering
| only things that would be displayed at the time for the user.
| TheCoelacanth wrote:
| > pagination or other ways of rendering only things that
| would be displayed at the time for the user
|
| Well, yes, those are alternate ways to deal performance
| problems, but they are not necessarily any easier than
| adding a bit of memoization.
| eatonphil wrote:
| No those solutions (and problems) were completely tangent
| to adding memoization. My point is that I've never seen a
| performance issue where non-memoization was the problem.
| cheeew wrote:
| I've normally heeded to the advice from Dan Abramov
| (https://overreacted.io/before-you-memo/) and KCD
| (https://kentcdodds.com/blog/usememo-and-usecallback): mainly due
| to the fact that I figured performance would take a significant
| hit by using unnecessary React.memo / useMemo calls throughout
| the codebase.
|
| One negative side-effect I could see as a result of this pattern
| is devs becoming too reliant on these optimizations and
| neglecting composition.
|
| But I suppose if the performance gain is substantial enough and
| DX isn't negatively impacted too much, it could serve as
| worthwhile-- especially at the level of scale which Coinbase
| requires.
| steve_adams_86 wrote:
| I don't disagree that this likely improves performance in most
| cases, and I don't blame the author here for any of my concerns.
|
| We've implemented this in our code base and it's awful. Yes it
| improves performance. It also makes debugging terrible. Combined
| with contexts, the react dev tools are virtually useless anywhere
| below a context with a memoized value.
|
| Profiling is harder because of frameworky misdirections as well.
| You can do coarse benchmarks but actually following code in a
| profile gets noticeably worse once you memo everything.
|
| I hope this is fixed. I really enjoy react, but this odd thing
| about it - that we arguably should memoize everything manually,
| and that it does make the dev tools a mess, is a huge hit to
| developer experience.
|
| So tired of "Component did not render" in the Component tab.
| jon-wood wrote:
| 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
| understanding of a child component's implementation to decide
| whether re-renders are needed, rather than allowing the child to
| communicate that up the tree.
| beaconstudios wrote:
| 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.
| FalconSensei wrote:
| 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
| jon-wood wrote:
| In which case, I stand corrected. I've not used React for a
| while and wasn't aware that was possible.
| ramesh31 wrote:
| Have you ever dug through a complex heavily nested application
| trying to debug a performance issue, only to find a custom
| shouldComponentUpdate method within every individual component?
| It makes debugging an absolute nightmare.
| brundolf wrote:
| I'm not sure why it would. The profiler will tell you exactly
| which component is the bottleneck, and you could then go
| inspect that one for the cause.
| ramesh31 wrote:
| >The profiler will tell you exactly which component is the
| bottleneck, and you could then go inspect that one for the
| cause.
|
| And then you have to understand the entire thought process
| and business logic that led to how the
| shouldComponentUpdate method for that class is implemented
| for every bottleneck, where one mistake or oversight can
| lead to an infinite re-render loop. This is the kind of
| stuff that should be handled at the framework level or with
| your state management library, not individual components.
| psadri wrote:
| What is your proposed alternative?
| notpachet wrote:
| Not the OP, but in a word: Redux.
| nsonha wrote:
| no?
|
| If you want state management you use a state management
| library. If you want optimization, you do memo, or pure
| component. You don't rely on the fact that some state
| library does that for you. You don't want your
| component's performance changes drastically when you
| refactor to context or whatever
| kecupochren wrote:
| What? Redux doesn't do any performance optimizations.
| notpachet wrote:
| Not by itself, but most people who use React + Redux use
| the (unsurprisingly named) react-redux glue library, too.
| That does a lot of the "should component update"
| calculations for you as a function of the computed
| `map[State/Dispatch]ToProps` result. (There are still
| some gotchas with caching selectors and so on, but I
| personally find those a lot easier to implement post-fact
| than memoizing hook soup codebases once you realize you
| have a problem.)
| kecupochren wrote:
| Oh, I never knew that. TIL
| ramesh31 wrote:
| >What is your proposed alternative?
|
| Precisely what the post describes. Functional components
| and memoize all the things.
| nathias wrote:
| This is an antipattern for a reason. Not only is the code less
| readable, it builds bad habits of code splitting state management
| and overall structure. A much better alternative is to just learn
| to understand the tools you are using better.
| jbaudanza wrote:
| 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).
| d23 wrote:
| I have basically no interest in frontend stuff, but I can't stop
| staring at this page. I think it's the overall color scheme and
| that body font. It's gorgeous.
| ald890 wrote:
| I created the benchmark for this.
|
| Because in every aspect it seems that React.memo is better.
| Especially when we are sure of stable argument references.
|
| Even when you add children to the component with memo, the worst
| case performance will be the same.
|
| https://codesandbox.io/s/react-memo-benchmark-m2bk6?file=/sr...
| Arch-TK wrote:
| This was in 2020. I assume the team got made redundant in the
| last year or something. Coinbase has genuinely been the slowest
| performing website I've used in the past couple of years.
| fabiendem wrote:
| I asked the author on Twitter if this approach was still in
| place, but didn't get a reply :/
| steadicat wrote:
| The team actually became part of a company-wide effort called
| Client Foundations! And no, we haven't changed our mind on
| this. (BTW we're hiring. :))
| have_faith wrote:
| It certainly feels like a failing of the hooks design that these
| subjects are so common (I love hooks generally!). When someone
| introduces a new paradigm that by design has a list of footguns
| to avoid you can't help but wonder if this was necessary.
|
| Has anyone tried tackling a hooks-like api that fixes the known
| pitfalls? encapsulating shared logic with hooks is a massive
| benefit but the subtleties can be difficult to teach to others.
| meowtimemania wrote:
| Has anyone added a compilation step that adds all the memoization
| boilerplate for you?
| hyzyla wrote:
| I think it can be a solution to readability problem
| Zababa wrote:
| There's no mention of what I think is the most important point:
| how is this enforced? If that's with a tool, I think it's great
| and a sane way to do things. If it's by asking everyone to
| remember doing it, I think it's a missed opportunity.
|
| It's also interesting to see the age-old functional programming
| problem: you trade performance for ease of development. I think
| these days people assume that things like immutable data
| structures are optimised under the hood. That doesn't seem to be
| the case with React, as you have to explicitly use a performance
| trick everywhere.
|
| Their argument that it would be premature optimisation to think
| about where memo is not needed makes sense, it's an interesting
| shift of optimisation of the runtime performance vs optimisation
| of the dev time.
|
| > Using memo and its cousins everywhere is a sane default. It's
| like a mask mandate during a coronavirus pandemic. Sure, we could
| have everybody tested every day and only ask people who are
| actively contagious to wear a mask. But it's far cheaper,
| simpler, and ultimately more effective to ask everybody to wear a
| mask by default.
|
| That's a good metaphor. It's easier for the people who decide, by
| shifting the burden on everyone else. I personally get headaches
| by wearing a mask all the time at work. I think I may get
| headaches too if I had to remember something like this all the
| time.
| nfRfqX5n wrote:
| I think it would be easy to create a rule to see if the default
| export is wrapped in memo, but you could also just have it as a
| coding standard
| BinaryBullet wrote:
| I wonder if this is the plugin they are using:
|
| https://github.com/steadicat/eslint-plugin-react-memo
|
| Does anyone know of any other eslint plugins that help
| enforce this?
| fabiendem wrote:
| The author of the article wrote the ESLint plugin:
| https://github.com/steadicat So they probably use(d) it.
| Zababa wrote:
| That's great!
| Zababa wrote:
| What do you mean by coding standard? My point was that if
| it's enforced by tool, either as a reminder, or an automatic
| modification, it's fine, but if it's not, it's annoying.
| jamespwilliams wrote:
| Kind of makes you wonder why React.memo isn't just the default
| behaviour.
|
| https://github.com/facebook/react/issues/14463#issuecomment-...
| suggests it was meant to be the default behaviour, but was
| scrapped because it would "break backwards compatibility". No
| source is given for that claim though.
| baxuz wrote:
| https://overreacted.io/before-you-memo/
|
| https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...
___________________________________________________________________
(page generated 2021-10-25 23:02 UTC)