diff --git a/src/components/toast/methods.tsx b/src/components/toast/methods.tsx
index eb465ecb4b..073aa33207 100644
--- a/src/components/toast/methods.tsx
+++ b/src/components/toast/methods.tsx
@@ -1,10 +1,10 @@
import React from 'react'
-import { InternalToast, ToastProps } from './toast'
-import { mergeProps } from '../../utils/with-default-props'
import {
ImperativeHandler,
renderImperatively,
} from '../../utils/render-imperatively'
+import { mergeProps } from '../../utils/with-default-props'
+import { InternalToast, ToastProps } from './toast'
let currentHandler: ImperativeHandler | null = null
let currentTimeout: number | null = null
@@ -42,7 +42,12 @@ export function show(p: ToastShowProps | string) {
/>
)
if (currentHandler) {
- currentHandler.replace(element)
+ if (currentHandler.isRendered?.()) {
+ currentHandler.replace(element)
+ } else {
+ currentHandler.close()
+ currentHandler = renderImperatively(element)
+ }
} else {
currentHandler = renderImperatively(element)
}
diff --git a/src/components/toast/tests/toast.test.tsx b/src/components/toast/tests/toast.test.tsx
index 0d17950bb6..ead30b541e 100644
--- a/src/components/toast/tests/toast.test.tsx
+++ b/src/components/toast/tests/toast.test.tsx
@@ -1,11 +1,11 @@
import React, { useRef } from 'react'
import {
- render,
+ act,
fireEvent,
+ render,
+ screen,
waitFor,
waitForElementToBeRemoved,
- act,
- screen,
} from 'testing'
import Toast, { ToastHandler } from '..'
@@ -255,4 +255,26 @@ describe('Toast', () => {
await waitForContentShow('content2')
expect(document.querySelectorAll(`.${classPrefix}-main`).length)
})
+
+ test('multiple toasts should show last one', async () => {
+ const { getByText } = render(
+
+ )
+ fireEvent.click(getByText('btn'))
+ await waitForContentShow('content2')
+ expect(document.querySelectorAll(`.${classPrefix}-main`).length)
+ })
})
diff --git a/src/utils/render-imperatively.tsx b/src/utils/render-imperatively.tsx
index 00a6fac198..bf5c8ec37f 100644
--- a/src/utils/render-imperatively.tsx
+++ b/src/utils/render-imperatively.tsx
@@ -1,5 +1,5 @@
-import React, { useEffect, useImperativeHandle, useRef, useState } from 'react'
import type { ReactElement } from 'react'
+import React, { useEffect, useImperativeHandle, useRef, useState } from 'react'
import { renderToBody } from './render-to-body'
type ImperativeProps = {
@@ -13,6 +13,7 @@ type TargetElement = ReactElement
export type ImperativeHandler = {
close: () => void
replace: (element: TargetElement) => void
+ isRendered?: () => boolean
}
export function renderImperatively(element: TargetElement) {
@@ -60,6 +61,8 @@ export function renderImperatively(element: TargetElement) {
if (!wrapperRef.current) {
// it means the wrapper is not mounted yet, call `unmount` directly
unmount()
+ // call `afterClose` to make sure the callback is called
+ element.props.afterClose?.()
} else {
wrapperRef.current?.close()
}
@@ -67,5 +70,6 @@ export function renderImperatively(element: TargetElement) {
replace: element => {
wrapperRef.current?.replace(element)
},
+ isRendered: () => !!wrapperRef.current,
} as ImperativeHandler
}