-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: re-render Background only if a larger image is needed #782
Conversation
Bug Fixes
Code Refactoring
Chore
ContributorsCommit-Lint commandsYou can trigger Commit-Lint actions by commenting on this PR:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good! It seems like the initial implementation really was quite broken.
Something else I was wondering when reading this: does this change the re-rendering behaviour that is ultimately caused by react-measure? i.e. is shouldComponentUpdate
continuously called? Or is this actually stopping react-measure from trying to re-render constantly?
super(props); | ||
} | ||
|
||
shouldComponentUpdate(nextProps) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also needs to handle cases when other props change, e.g. imgixParams
, disableLibraryParam
, etc.
The original behavior is re-rendering occurs from the moment of first-render onward. The component re-renders ~70 times per second (and there's nothing stopping it, this is also "70 times per second without resizing the browser"). The new behavior renders 3 times on first render which is expected given how
Now we can count renders: Visually, this first image is the number of renders with the original component mounting for the first time only. No resizing occurs and I only recorded for 1.3s (e.g. 78th of 78 renders at 1.3s). This image is of how the updated component renders. I started out with a small browser window and upsized a few times. Here the component actually needs to update; it does so at the 13.4s mark. From this you can see the improvement over rendering 70x/sec. And here is the final update, but only to the underlying Now, there is room for improvement here. |
Thanks for the in depth reply here @ericdeansanchez! |
// If we made it here, we need to check if the "top-level" | ||
// props have changed (e.g. disableLibraryParam). | ||
const shallowPropsEqual = shallowEqual(this.props, nextProps); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be more than we eventually want to check for, but I think it's a good enough starting point for now 👍
🎉 This PR is included in version 9.1.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
nextProps.imgixParams | ||
); | ||
|
||
return shallowPropsEqual && shallowParamsEqual; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great so far! Two things that should be done here:
imgixParams
shouldn't be checked on L52htmlAtrtibutes
should also be shallowly compared.
This could be done like this:
const customizer = (value, other, key) => {
if (key === "imgixParams" || key === "htmlAttributes") {
return shallowEqual(value, other);
}
return undefined; // Use default behaviour
};
// If we made it here, we need to check if the "top-level"
// props have changed (e.g. disableLibraryParam).
const shallowPropsEqual = shallowEqual(this.props, nextProps, customizer);
return shallowPropsEqual;
The purpose of this PR is to keep as much of the original behavior of the
Background
component as possible while curbing the number of timesthis component re-renders. Prior, this component re-renders an "infinite"
number of times. Really, it doesn't stop re-rendering.
Now, this component re-renders on a more appropriate interval. Prior,
this component would re-render beginning with the first render. This
means that if you were to render a
Background
component withoutresizing the browser at all it would render a few hundred times in the span
of a couple seconds. Now, there are three initial renders.
This rendering behavior is expected given the behavior of react-measure
in this case.
Prior (and ignoring the continuous rendering behavior), this component
could re-render if height/width changed. Now, this component will
only be re-rendered if height/width have increased.
Closes #387