Skip to content
Snippets Groups Projects
Commit 3d2f938c authored by Tom Robinson's avatar Tom Robinson Committed by GitHub
Browse files

Merge pull request #3058 from metabase/tooltip-fix

	Fix issue with unmounting open tooltips causing crashes
parents 36a438da 41dc3cce
No related branches found
No related tags found
No related merge requests found
......@@ -199,7 +199,6 @@ angular.module('metabase', [
}])
.controller('AppController', ['$scope', '$location', '$route', '$routeParams', '$rootScope', '$timeout', 'ipCookie', 'AppState',
function($scope, $location, $route, $routeParams, $rootScope, $timeout, ipCookie, AppState) {
console.log("creating store");
$scope.Component = Routes;
$scope.props = {
onChangeLocation(url) {
......
......@@ -8,11 +8,9 @@ export default class Tooltip extends Component {
super(props, context);
this.state = {
isOpen: false
isOpen: false,
isHovered: false
};
this._onMouseEnter = this._onMouseEnter.bind(this);
this._onMouseLeave = this._onMouseLeave.bind(this);
}
static propTypes = {
......@@ -29,8 +27,17 @@ export default class Tooltip extends Component {
componentDidMount() {
let elem = ReactDOM.findDOMNode(this);
elem.addEventListener("mouseenter", this._onMouseEnter, false);
elem.addEventListener("mouseleave", this._onMouseLeave, false);
// HACK: These two event listeners ensure that if a click on the child causes the tooltip to
// unmount (e.x. navigating away) then the popover is removed by the time this component
// unmounts. Previously we were seeing difficult to debug error messages like
// "Cannot read property 'componentDidUpdate' of null"
elem.addEventListener("mousedown", this._onMouseDown, true);
elem.addEventListener("mouseup", this._onMouseUp, true);
this._element = document.createElement('div');
this.componentDidUpdate();
}
......@@ -52,17 +59,31 @@ export default class Tooltip extends Component {
let elem = ReactDOM.findDOMNode(this);
elem.removeEventListener("mouseenter", this._onMouseEnter, false);
elem.removeEventListener("mouseleave", this._onMouseLeave, false);
elem.removeEventListener("mousedown", this._onMouseDown, true);
elem.removeEventListener("mouseup", this._onMouseUp, true);
ReactDOM.unmountComponentAtNode(this._element);
clearTimeout(this.timer);
}
_onMouseEnter(e) {
this.setState({ isOpen: true });
_onMouseEnter = (e) => {
this.setState({ isOpen: true, isHovered: true });
}
_onMouseLeave(e) {
_onMouseLeave = (e) => {
this.setState({ isOpen: false, isHovered: false });
}
_onMouseDown = (e) => {
this.setState({ isOpen: false });
}
_onMouseUp = (e) => {
// This is in a timeout to ensure the component has a chance to fully unmount
this.timer = setTimeout(() =>
this.setState({ isOpen: this.state.isHovered })
, 0);
}
render() {
return React.Children.only(this.props.children);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment