diff --git a/CHANGELOG.md b/CHANGELOG.md index 523119ab7f9..8b4de4b99ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - `EuiButton`, `EuiButtonEmpty`, and `EuiButtonIcon` now look and behave disabled when `isDisabled={true}` ([#862](https://github.com/elastic/eui/pull/862)) - `EuiGlobalToastList` no longer triggers `Uncaught TypeError: _this.callback is not a function` ([#865](https://github.com/elastic/eui/pull/865)) +- `EuiGlobalToastList` checks to see if it has dismissed a toast before re-dismissing it ([#868](https://github.com/elastic/eui/pull/868)) ## [`0.0.49`](https://github.com/elastic/eui/tree/v0.0.49) diff --git a/src/components/toast/global_toast_list.js b/src/components/toast/global_toast_list.js index 33b38e86e6d..d2717139897 100644 --- a/src/components/toast/global_toast_list.js +++ b/src/components/toast/global_toast_list.js @@ -108,18 +108,24 @@ export class EuiGlobalToastList extends Component { dismissToast = (toast) => { // Remove the toast after it's done fading out. this.dismissTimeoutIds.push(setTimeout(() => { - this.props.dismissToast(toast); - this.toastIdToTimerMap[toast.id].clear(); - delete this.toastIdToTimerMap[toast.id]; - - this.setState(prevState => { - const toastIdToDismissedMap = { ...prevState.toastIdToDismissedMap }; - delete toastIdToDismissedMap[toast.id]; - - return { - toastIdToDismissedMap, - }; - }); + // Because this is wrapped in a setTimeout, and because React does not guarantee when + // state updates happen, it is possible to double-dismiss a toast + // including by double-clicking the "x" button on the toast + // so, first check to make sure we haven't already dismissed this toast + if (this.toastIdToTimerMap.hasOwnProperty(toast.id)) { + this.props.dismissToast(toast); + this.toastIdToTimerMap[toast.id].clear(); + delete this.toastIdToTimerMap[toast.id]; + + this.setState(prevState => { + const toastIdToDismissedMap = { ...prevState.toastIdToDismissedMap }; + delete toastIdToDismissedMap[toast.id]; + + return { + toastIdToDismissedMap, + }; + }); + } }, TOAST_FADE_OUT_MS)); this.setState(prevState => {