I have been struggling with a performance problem in a React (React Native to be exact) app for days. It boils down to this problem:
When a Parent
function component has another function component as the Child
, the Parent
will always re-renders whenever its own parent (GrandParent
) re-renders. And this is true even if all components are memoized with React.memo
.
It seems to be a fundamental problem for React, because in this common situation, HeavyParent
will always re-renders whenever LightGrandParent
re-renders, even if neither HeavyParent
nor LightChild
needs re-rendering. This is obviously causing a massive performance problem for our app.
<LightGrandParent>
<HeavyParent>
<LightChild />
</HeavyParent>
</LightGrandParent>
I can't believe this is how React works. Did I miss anything?
I created a sandbox to show what I mean.
A component re-renders if its state changes, or when its parent re-renders. Re-renders on state changes are normal. The other case sometimes is problematic. In this components tree you pasted
<LightGrandParent>
<HeavyParent>
<LightChild />
</HeavyParent>
</LightGrandParent>
LightGrandParent
consumes HeavyParent
with props.children
, which gives you out of the box optimization, as React won't re-renders HeavyParent
if LightGrandParent
re-renders because of an internal state
change.
Now, if you wanna also control re-renders because of LightGrandParent
's parent re-rendering, you could use memo
to memoize HeavyParent
.
But this won't work because HeavyParent
consumes LightChild
as children
, which is a new refrence on each render, and memo
comparing new props with previous to do caching.
The answers @yousumar and a few other folks provided were correct. However, this also means a very surprising phenomenon demonstrated as follows:
I know many developers won't see this as a problem and will just say "hey this is how it works". But I personally think that this at least represents a shortcoming in React's fundamentals, as it violates the principle of least surprise. Also React's core doc should have pointed this out so that developers like me wouldn't get burned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With