45 lines
1.0 KiB
TypeScript
45 lines
1.0 KiB
TypeScript
import { useEffect, useState } from "react";
|
||
import { createPortal } from "react-dom";
|
||
import { type MessageItem, addFn, removeFn } from "./utils";
|
||
|
||
import styles from "./message.module.less";
|
||
|
||
function Message() {
|
||
const [message, setMessage] = useState<MessageItem>();
|
||
|
||
useEffect(() => {
|
||
const fn = (nextMessage: MessageItem) => {
|
||
const key = `${Math.ceil(performance.now())}-${Math.round(Math.random() * 100)}`;
|
||
|
||
setMessage({ ...nextMessage, key });
|
||
|
||
setTimeout(() => {
|
||
onClose();
|
||
}, nextMessage.duration || 5000);
|
||
};
|
||
|
||
addFn(fn);
|
||
|
||
return () => {
|
||
removeFn(fn);
|
||
};
|
||
}, []);
|
||
|
||
const onClose = () => {
|
||
setMessage(undefined);
|
||
}
|
||
|
||
return createPortal((
|
||
<div className={styles.message}>
|
||
{message && (
|
||
<div key={message.key} className={styles.item}>
|
||
<span className={styles.content}>{message.content}</span>
|
||
<button className={styles.close} onClick={() => onClose()}>×</button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
), document.body);
|
||
}
|
||
|
||
export default Message;
|