From bc5ae6a6ad47ea38aa080185fd66ff0563ce279e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 4 Mar 2016 14:51:55 +0000 Subject: [PATCH] Add shouldComponentUpdate() methods to RoomView and TimelinePanel This will avoid re-rendering the whole RoomView every time we get a scroll event, and might even help with https://github.com/vector-im/vector-web/issues/1056. --- src/ObjectUtils.js | 31 ++++++++++++++++++++++ src/components/structures/RoomView.js | 6 +++++ src/components/structures/TimelinePanel.js | 6 +++++ 3 files changed, 43 insertions(+) diff --git a/src/ObjectUtils.js b/src/ObjectUtils.js index 41dc34cca7..07a16df501 100644 --- a/src/ObjectUtils.js +++ b/src/ObjectUtils.js @@ -77,3 +77,34 @@ module.exports.getKeyValueArrayDiffs = function(before, after) { return results; }; + +/** + * Shallow-compare two objects for equality: each key and value must be + * identical + */ +module.exports.shallowEqual = function(objA, objB) { + if (objA === objB) { + return true; + } + + if (typeof objA !== 'object' || objA === null || + typeof objB !== 'object' || objB === null) { + return false; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + for (var i = 0; i < keysA.length; i++) { + var key = keysA[i]; + if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) { + return false; + } + } + + return true; +}; diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 3cd933eaaa..6304cc4f48 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -38,6 +38,7 @@ var SlashCommands = require("../../SlashCommands"); var dis = require("../../dispatcher"); var Tinter = require("../../Tinter"); var rate_limited_func = require('../../ratelimitedfunc'); +var ObjectUtils = require('../../ObjectUtils'); var DEBUG = false; @@ -164,6 +165,11 @@ module.exports = React.createClass({ } }, + shouldComponentUpdate: function(nextProps, nextState) { + return (!ObjectUtils.shallowEqual(this.props, nextProps) || + !ObjectUtils.shallowEqual(this.state, nextState)); + }, + componentWillUnmount: function() { // set a boolean to say we've been unmounted, which any pending // promises can use to throw away their results. diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 6d034721a5..b7c2f24dd3 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -24,6 +24,7 @@ var EventTimeline = Matrix.EventTimeline; var sdk = require('../../index'); var MatrixClientPeg = require("../../MatrixClientPeg"); var dis = require("../../dispatcher"); +var ObjectUtils = require('../../ObjectUtils'); var PAGINATE_SIZE = 20; var INITIAL_SIZE = 20; @@ -145,6 +146,11 @@ var TimelinePanel = React.createClass({ } }, + shouldComponentUpdate: function(nextProps, nextState) { + return (!ObjectUtils.shallowEqual(this.props, nextProps) || + !ObjectUtils.shallowEqual(this.state, nextState)); + }, + componentWillUnmount: function() { // set a boolean to say we've been unmounted, which any pending // promises can use to throw away their results.