commit: b00cb2aed3634ad6624e144b99d538eb85c58c12
parent: 7c67cb599713cfeec4bdcb5447f36718886da2be
Author: Nolan Lawson <nolan@nolanlawson.com>
Date: Fri, 26 May 2017 05:05:52 -0700
Improve shouldComponentUpdate for status and status_action_bar (#3323)
Diffstat:
2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js
@@ -44,6 +44,35 @@ class Status extends ImmutablePureComponent {
isHidden: false,
}
+ // Avoid checking props that are functions (and whose equality will always
+ // evaluate to false. See react-immutable-pure-component for usage.
+ updateOnProps = [
+ 'status',
+ 'account',
+ 'wrapped',
+ 'me',
+ 'boostModal',
+ 'autoPlayGif',
+ 'muted',
+ ]
+
+ updateOnStates = []
+
+ shouldComponentUpdate (nextProps, nextState) {
+ if (nextProps.isIntersecting === false && nextState.isHidden) {
+ // It's only if we're not intersecting (i.e. offscreen) and isHidden is true
+ // that either "isIntersecting" or "isHidden" matter, and then they're
+ // the only things that matter.
+ return this.props.isIntersecting !== false || !this.state.isHidden;
+ } else if (nextProps.isIntersecting !== false && this.props.isIntersecting === false) {
+ // If we're going from a non-intersecting state to an intersecting state,
+ // (i.e. offscreen to onscreen), then we definitely need to re-render
+ return true;
+ }
+ // Otherwise, diff based on "updateOnProps" and "updateOnStates"
+ return super.shouldComponentUpdate(nextProps, nextState);
+ }
+
componentWillReceiveProps (nextProps) {
if (nextProps.isIntersecting === false && this.props.isIntersecting !== false) {
requestIdleCallback(() => this.setState({ isHidden: true }));
@@ -52,14 +81,6 @@ class Status extends ImmutablePureComponent {
}
}
- shouldComponentUpdate (nextProps, nextState) {
- if (nextProps.isIntersecting === false && this.props.isIntersecting !== false) {
- return nextState.isHidden;
- }
-
- return true;
- }
-
handleRef = (node) => {
if (this.props.onRef) {
this.props.onRef(node);
diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import IconButton from './icon_button';
import DropdownMenu from './dropdown_menu';
import { defineMessages, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
@@ -21,7 +22,7 @@ const messages = defineMessages({
unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' },
});
-class StatusActionBar extends React.PureComponent {
+class StatusActionBar extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
@@ -43,6 +44,14 @@ class StatusActionBar extends React.PureComponent {
intl: PropTypes.object.isRequired,
};
+ // Avoid checking props that are functions (and whose equality will always
+ // evaluate to false. See react-immutable-pure-component for usage.
+ updateOnProps = [
+ 'status',
+ 'me',
+ 'withDismiss',
+ ]
+
handleReplyClick = () => {
this.props.onReply(this.props.status, this.context.router);
}