From 83696eebb3f6dda944efc96f25297311e0e81563 Mon Sep 17 00:00:00 2001 From: Chandler Date: Wed, 23 May 2018 09:58:14 -0600 Subject: [PATCH] make sure a toast has not already been dismissed when dismissing it (#868) * make sure a toast has not already been dismissed when dismissing it * changelog --- CHANGELOG.md | 1 + src/components/toast/global_toast_list.js | 30 ++++++++++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) 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 => {