From d228d49c7d0388bfbfa7800d4bd7826b44b2cdf3 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 17 Aug 2017 22:44:13 +0700 Subject: [PATCH] Optimize rendering when `activeReplyBox` changes --- .../src/components/Comment.js | 31 ++++++++++++++++++- .../coral-embed-stream/src/graphql/utils.js | 6 +++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index cc1ee7bed..d34de96ac 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -16,13 +16,14 @@ import mapValues from 'lodash/mapValues'; import LoadMore from './LoadMore'; import {getEditableUntilDate} from './util'; +import {findCommentWithId} from '../graphql/utils'; import {TopRightMenu} from './TopRightMenu'; import CommentContent from './CommentContent'; import Slot from 'coral-framework/components/Slot'; import IgnoredCommentTombstone from './IgnoredCommentTombstone'; import InactiveCommentLabel from './InactiveCommentLabel'; import {EditableCommentContent} from './EditableCommentContent'; -import {getActionSummary, iPerformedThisAction, forEachError, isCommentActive} from 'coral-framework/utils'; +import {getActionSummary, iPerformedThisAction, forEachError, isCommentActive, getShallowChanges} from 'coral-framework/utils'; import t from 'coral-framework/services/i18n'; import CommentContainer from '../containers/Comment'; @@ -73,6 +74,17 @@ const ActionButton = ({children}) => { ); }; +// Determine whether the comment with id is in the part of the comments tree. +function containsCommentId(props, id) { + if (props.comment.id === id) { + return true; + } + if (props.comment.replies) { + return findCommentWithId(props.comment.replies.nodes, id); + } + return false; +} + export default class Comment extends React.Component { constructor(props) { @@ -112,6 +124,23 @@ export default class Comment extends React.Component { } } + shouldComponentUpdate(next) { + + // Specifically handle `activeReplyBox` if it is the only change. + const changes = getShallowChanges(this.props, next); + if (changes.length === 1 && changes[0] === 'activeReplyBox') { + if ( + !containsCommentId(next, this.props.activeReplyBox) && + !containsCommentId(next, next.activeReplyBox) + ) { + return false; + } + } + + // Prevent Slot from rerendering when no props has shallowly changed. + return changes.length !== 0; + } + static propTypes = { // id of currently opened ReplyBox. tracked in Stream.js diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index ac6298616..11d3d411b 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -117,7 +117,7 @@ export function getTopLevelParent(comment) { return comment; } -function findComment(nodes, callback) { +export function findComment(nodes, callback) { for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if (callback(node)) { @@ -133,6 +133,10 @@ function findComment(nodes, callback) { return false; } +export function findCommentWithId(nodes, id) { + return findComment(nodes, (node) => node.id === id); +} + export function findCommentInEmbedQuery(root, callbackOrId) { let callback = callbackOrId; if (typeof callbackOrId === 'string') {