diff --git a/CHANGELOG.md b/CHANGELOG.md index ff1253a6feb..b199ae81720 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - `EuiBasicTable` select all shows up on mobile ([#1462](https://github.com/elastic/eui/pull/1462)) - Adds missing `hasActiveFilters` prop for `EuiFilterButton` type and fixes `onChange` signature for `EuiButtonGroup` ([#1603](https://github.com/elastic/eui/pull/1603)) +- Prevent `EuiGlobalToastList` from attempting calculations on `null` DOM elements ([#1606](https://github.com/elastic/eui/pull/1606)) **Breaking changes** diff --git a/src/components/toast/global_toast_list.js b/src/components/toast/global_toast_list.js index d2717139897..98d7f161f99 100644 --- a/src/components/toast/global_toast_list.js +++ b/src/components/toast/global_toast_list.js @@ -23,6 +23,11 @@ export class EuiGlobalToastList extends Component { this.isScrollingToBottom = false; this.isScrolledToBottom = true; + + // See [Return Value](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame#Return_value) + // for information on initial value of 0 + this.isScrollingAnimationFrame = 0; + this.startScrollingAnimationFrame = 0; } static propTypes = { @@ -40,6 +45,10 @@ export class EuiGlobalToastList extends Component { this.isScrollingToBottom = true; const scrollToBottom = () => { + // Although we cancel the requestAnimationFrame in componentWillUnmount, + // it's possible for this.listElement to become null in the meantime + if (!this.listElement) return; + const position = this.listElement.scrollTop; const destination = this.listElement.scrollHeight - this.listElement.clientHeight; const distanceToDestination = destination - position; @@ -54,11 +63,11 @@ export class EuiGlobalToastList extends Component { this.listElement.scrollTop = position + distanceToDestination * 0.25; if (this.isScrollingToBottom) { - window.requestAnimationFrame(scrollToBottom); + this.isScrollingAnimationFrame = window.requestAnimationFrame(scrollToBottom); } }; - window.requestAnimationFrame(scrollToBottom); + this.startScrollingAnimationFrame = window.requestAnimationFrame(scrollToBottom); } onMouseEnter = () => { @@ -162,6 +171,12 @@ export class EuiGlobalToastList extends Component { } componentWillUnmount() { + if (this.isScrollingAnimationFrame !== 0) { + window.cancelAnimationFrame(this.isScrollingAnimationFrame); + } + if (this.startScrollingAnimationFrame !== 0) { + window.cancelAnimationFrame(this.startScrollingAnimationFrame); + } this.listElement.removeEventListener('scroll', this.onScroll); this.listElement.removeEventListener('mouseenter', this.onMouseEnter); this.listElement.removeEventListener('mouseleave', this.onMouseLeave);