Before You Memo()
overreacted.io
overreacted.io
- 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.
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".
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.
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.
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.
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.
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.
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.