From cded632fd2b65bc2bebfd6e0d4f41ed59ac527b8 Mon Sep 17 00:00:00 2001 From: infinite-persistence <64950861+infinite-persistence@users.noreply.github.com> Date: Tue, 25 May 2021 06:29:58 +0800 Subject: [PATCH] DateTime: avoid unnecessary update (#6110) ## Issue Part of `5834 Performance investigation` In a homepage with 120 tiles, the lists get rendered 3 times during initial update. The sub-components are updating recursively (will investigate), so instead of 120 DateTime renders, we have 1000+ renders. The resolved DateTime string for `timeAgo` rarely changes, and even if the string was "a few seconds ago", there's no real need to constantly update it. ## Change Require a minimum 1-minute delta when deciding whether the component should update. Clients can change this value as needed. ## Test - [x] Verified `shouldComponentUpdate` doesn't end up taking more time than not having it (it's in micro-second range, compared to the millisecond render). - [x] Profiler showed no significant improvement for low number of DateTime components, but for the 120 DateTime case, almost 1/4 of a second is saved. --- ui/component/dateTime/view.jsx | 52 ++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/ui/component/dateTime/view.jsx b/ui/component/dateTime/view.jsx index 2745db100..a372cbd74 100644 --- a/ui/component/dateTime/view.jsx +++ b/ui/component/dateTime/view.jsx @@ -2,15 +2,29 @@ import React from 'react'; import moment from 'moment'; +const DEFAULT_MIN_UPDATE_DELTA_MS = 60 * 1000; + type Props = { date?: any, timeAgo?: boolean, - formatOptions: {}, + formatOptions?: {}, show?: string, - clock24h: boolean, + clock24h?: boolean, + minUpdateDeltaMs?: number, }; -class DateTime extends React.PureComponent { +type State = { + lastRenderTime: Date, +}; + +class DateTime extends React.Component { + constructor(props: Props) { + super(props); + this.state = { + lastRenderTime: new Date(), + }; + } + static SHOW_DATE = 'date'; static SHOW_TIME = 'time'; @@ -45,6 +59,38 @@ class DateTime extends React.PureComponent { return __(strId, { duration }); } + shouldComponentUpdate(nextProps: Props): boolean { + if ( + moment(this.props.date).diff(moment(nextProps.date)) !== 0 || + this.props.clock24h !== nextProps.clock24h || + this.props.timeAgo !== nextProps.timeAgo || + this.props.minUpdateDeltaMs !== nextProps.minUpdateDeltaMs || + this.props.show !== nextProps.show + ) { + return true; + } + + if (this.props.timeAgo && nextProps.timeAgo) { + const minUpdateDeltaMs = this.props.minUpdateDeltaMs || DEFAULT_MIN_UPDATE_DELTA_MS; + const prev = moment(this.state.lastRenderTime); + const curr = moment(new Date()); + const deltaMs = curr.diff(prev); + + if (deltaMs > minUpdateDeltaMs) { + return true; + } + } + + return false; + } + + componentDidUpdate() { + const { timeAgo } = this.props; + if (timeAgo) { + this.setState({ lastRenderTime: new Date() }); + } + } + render() { const { date, timeAgo, show, clock24h } = this.props;