Skip to content

Commit

Permalink
refactor(instance): Migrate the instance chiclet tooltip from raw boo…
Browse files Browse the repository at this point in the history
…tstrap to Tooltip component (#8437)

This commit includes a performance optimization where tooltips are only shown after the chiclet has been hovered.  Otherwise, the Tooltip causes massive lag n screens with large number of instances. This happens when scrolling due to virtualized scrolling and the overhad of the mount/unmount cycle.

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
christopherthielen and mergify[bot] committed Jul 30, 2020
1 parent 75f2328 commit 64cd209
Showing 1 changed file with 22 additions and 39 deletions.
61 changes: 22 additions & 39 deletions app/scripts/modules/core/src/instance/Instance.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import $ from 'jquery';

import classNames from 'classnames';
import { IInstance } from 'core/domain';
import { Tooltip } from '../presentation';

export interface IInstanceProps {
instance: IInstance;
Expand All @@ -10,45 +11,27 @@ export interface IInstanceProps {
onInstanceClicked(instance: IInstance): void;
}

export class Instance extends React.Component<IInstanceProps> {
private $tooltipElement: JQuery = null;
export const Instance = React.memo(function Instance(props: IInstanceProps) {
const { instance, active, highlight, onInstanceClicked } = props;
const { name, id, healthState } = instance;
const [mouseOver, setMouseOver] = React.useState(false);

private handleClick = (event: React.MouseEvent<any>) => {
const handleClick = (event: React.MouseEvent<any>) => {
event.preventDefault();
this.props.onInstanceClicked(this.props.instance);
onInstanceClicked(instance);
};

public onMouseOver = (event: React.MouseEvent<any>) => {
this.$tooltipElement = $(event.target);
this.$tooltipElement.tooltip({ animation: false, container: 'body' } as JQueryUI.TooltipOptions).tooltip('show');
};

public shouldComponentUpdate(nextProps: IInstanceProps) {
const checkProps: Array<keyof IInstanceProps> = ['instance', 'active', 'highlight'];
return checkProps.some(key => this.props[key] !== nextProps[key]);
}

public componentWillUnmount() {
if (this.$tooltipElement) {
this.$tooltipElement.tooltip('destroy');
}
}

public render() {
const { instance, active, highlight } = this.props;
const { name, id, healthState } = instance;

const className = `instance health-status-${healthState} ${highlight === id ? 'highlighted' : ''} ${
active ? 'active' : ''
}`;
return (
<a
className={className}
title={name || id}
data-toggle="tooltip"
onMouseOver={this.onMouseOver}
onClick={this.handleClick}
/>
);
}
}
const className = classNames({ highlighted: highlight === id, active: active });
const anchor = (
<a
className={`instance health-status-${healthState} ${className}`}
title={name || id}
onMouseOver={() => setMouseOver(true)}
onMouseOut={() => setMouseOver(false)}
onClick={handleClick}
/>
);

// Perf optimization: do not render the Tooltip component unless we received an onMouseOver event
return mouseOver ? <Tooltip value={name || id}>{anchor}</Tooltip> : anchor;
});

0 comments on commit 64cd209

Please sign in to comment.