fix toast

This commit is contained in:
Pig Fang 2020-06-23 15:37:18 +08:00
parent 56ec01f32a
commit 7a78c612bf
3 changed files with 43 additions and 15 deletions

View File

@ -33,14 +33,10 @@ const Toast: React.FC<Props> = (props) => {
const [show, setShow] = useState(false) const [show, setShow] = useState(false)
useEffect(() => { useEffect(() => {
const id1 = setTimeout(() => setShow(true), 100) const timer = setTimeout(() => setShow(true), 100)
const id2 = setTimeout(() => setShow(false), 3000)
const id3 = setTimeout(props.onClose, 3100)
return () => { return () => {
clearTimeout(id1) clearTimeout(timer)
clearTimeout(id2)
clearTimeout(id3)
} }
}, [props.onClose]) }, [props.onClose])

View File

@ -13,12 +13,20 @@ const CLEAR_EVENT = Symbol('clear')
export const ToastContainer: React.FC = () => { export const ToastContainer: React.FC = () => {
const [queue, setQueue] = useState<ToastQueue>([]) const [queue, setQueue] = useState<ToastQueue>([])
const handleClose = (id: string) => {
setQueue((queue) => queue.filter((el) => el.id !== id))
}
useEffect(() => { useEffect(() => {
const off1 = emitter.on(TOAST_EVENT, (toast: QueueElement) => { const off1 = emitter.on(TOAST_EVENT, (toast: QueueElement) => {
setQueue((queue) => { setQueue((queue) => {
queue.push(toast) queue.push(toast)
return queue.slice() return queue.slice()
}) })
setTimeout(() => {
handleClose(toast.id)
}, 3100)
}) })
const off2 = emitter.on(CLEAR_EVENT, () => setQueue([])) const off2 = emitter.on(CLEAR_EVENT, () => setQueue([]))
@ -28,12 +36,9 @@ export const ToastContainer: React.FC = () => {
} }
}, []) }, [])
const handleClose = (id: string) => {
setQueue((queue) => queue.filter((el) => el.id !== id))
}
return ( return (
<> <>
{queue.length}
{queue.map((el, i) => ( {queue.map((el, i) => (
<ToastBox <ToastBox
key={el.id} key={el.id}
@ -49,11 +54,16 @@ export const ToastContainer: React.FC = () => {
} }
export class Toast { export class Toast {
constructor() { private container: HTMLDivElement
const container = document.createElement('div')
document.body.appendChild(container)
ReactDOM.render(<ToastContainer />, container) constructor() {
this.container = document.createElement('div')
document.body.appendChild(this.container)
/* istanbul ignore next */
if (process.env.NODE_ENV !== 'test') {
ReactDOM.render(<ToastContainer />, this.container)
}
} }
success(message: string) { success(message: string) {
@ -75,4 +85,12 @@ export class Toast {
clear() { clear() {
emitter.emit(CLEAR_EVENT) emitter.emit(CLEAR_EVENT)
} }
dispose() {
/* istanbul ignore next */
if (process.env.NODE_ENV !== 'test') {
ReactDOM.unmountComponentAtNode(this.container)
}
this.container.remove()
}
} }

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import { render } from '@testing-library/react' import { render, fireEvent, screen } from '@testing-library/react'
import { Toast, ToastContainer } from '@/scripts/toast' import { Toast, ToastContainer } from '@/scripts/toast'
test('"Toast" class', () => { test('"Toast" class', () => {
@ -25,6 +25,7 @@ test('"Toast" class', () => {
) )
jest.runAllTimers() jest.runAllTimers()
toast.dispose()
}) })
test('clear toasts', () => { test('clear toasts', () => {
@ -36,4 +37,17 @@ test('clear toasts', () => {
toast.clear() toast.clear()
expect(document.querySelectorAll('.alert')).toHaveLength(0) expect(document.querySelectorAll('.alert')).toHaveLength(0)
toast.dispose()
})
test('close toast manually', () => {
render(<ToastContainer />)
const toast = new Toast()
toast.success('success')
fireEvent.click(screen.getByText('×'))
expect(document.querySelectorAll('.alert')).toHaveLength(0)
toast.dispose()
}) })