Hacker News new | past | comments | ask | show | jobs | submit login
Before You Memo() (overreacted.io)
87 points by feross on Feb 27, 2021 | hide | past | favorite | 14 comments



Dan linked Kent's post on why the "same-element reference" bit matters at the bottom, but it's worth highlighting:

- https://kentcdodds.com/blog/optimize-react-re-renders

and I covered this as well in my extensive "Guide to React Rendering Behavior"

- https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...

Dan also had some follow-up thoughts on Twitter, starting here:

- https://twitter.com/dan_abramov/status/1364068524394749952

I think these are a couple key points:

> Here’s a different way to think about it. The core principle is just that if you can prove to React something can’t change (like this children prop, which is the same between renders because it comes from above), then React doesn’t need to visit it.

> To sum up, I don’t see it as a trick at all. I see it as a foundational principle for React optimizations. In simple cases, like in this post, you can use this principle yourself. But an optimizing compiler would apply the same exact principle to a broader set of cases.


I must admit I don't fully understand this, probably need to read your linked articles a bit more in-depth first.

But if you say react doesn't need to visit the children because the prop didn't change, you have to also answer the related question: Why does react need to visit the same JSX Element that receives the same props?

> To sum up, I don’t see it as a trick at all.

Like many react articles before, this really feels like post-hoc rationalization.

Getting the react API to be sane and predictable is really hard giving JS's current notion of equality.


React components are not pure functions. React tries to be declarative but at the end of the day, they couldn’t figure out how to get it to work without adding lifecycle callback functions, event listeners, reactive hooks, and overall dirtying the code with imperative constructs.

There are very good reasons for not passing every piece of data through props, but as a result, react components create side-effects, and those side-effects cause components to re-render even when the props don’t change. This is in order to prevent colloquially what we call “prop-drilling” which enables us to dynamically inject props into our react components via hooks. We also need a way to re-render when an event happens inside of a component.


Sure, but that still doesn’t explain the difference in rerendering between writing down the JSX element as a child or passing it in via props.


That JSX element is a function call, not a class that has a render method.

If that <ExpensiveComponent /> was a `class ExpensiveComponent extends React.PureComponent { render() { ... } }` it would not be an issue because diff algorithm can step in.

I think people are just recognizing that all of this stuff can be optimized away by a proper compiler and this will soon be done.

Nothing stops anyone from figuring out the dependencies and doing proper rerenders without diffing algorithms running on every change.


If expensive component extended React.PureComponent there would be no rerender.


Can only recommend your blog post! It's my goto website when I want to read in depth articles about React or Redux.

That being said, what struck me most was this piece of Dan's quote:

> [...]if you can prove to React something can’t change [...], then React doesn’t need to visit it

I mean it's the consequence of using memoization, but I never really put it that way and for some reason it helps me writing better code. It's a weird thing I have like "I only really realize/understand it when you give it a name or call it out".


Im a bit worried about the growing complexity of React. I have the same feeling about certain frameworks, like next.js. they seem to want to make a living and employ a small country constantly introducing new features to these frameworks. I've been using React since 2016 but with the constant intro of new stuff unless you are in the weeds of using this all the time you will quickly grow less adept at the framework over time.


As someone who had been building large react applications for a living for the better part of a decade, I’m inclined to agree.

React has been a massive success and I don’t plan on switching anytime soon, but it’s one of the few libraries that I cannot make heads or tails of the source code in a relatively quickly scan.

I think it will eventually buckle under its own weight.


If expensive component extended React.PureComponent instead of being just a function call it would still work.

New appearance of hooks and effects made people not use PureComponent class and replaced everything with functions that return JSX declared stuff. There’s no diffing happening this way.


How different is the React.PureComponent behavior from the "wrap stuff in React.memo()" behavior?


not much.


Classes made it easier to wrap things implicitly and "do the right thing", even if the developer doesn't know or care what you did.

With hooks, you need to do all these optimizations and best practices explicitly, which bloats up the code and defeats the purpose of getting rid of class structure boilerplate in the first place.


The longer I use React, the more I appreciate the power of being able to pass children to components.




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

Search: