import React from "react"; import without from "lodash/without"; import { useTranslation } from "react-i18next"; import { alertService, AlertInfoEx, kAlertHostId, AlertInfo, } from "@/services/alert"; import { convertI18nText } from "@/common"; interface AutoCloseAlertProps { alert: AlertInfo; close: () => void; } export const AutoCloseAlert: React.FC = (props) => { const { alert, close } = props; const { dismissTime } = alert; const { t } = useTranslation(); const timerTag = React.useRef(null); const closeHandler = React.useRef<(() => void) | null>(null); React.useEffect(() => { closeHandler.current = close; }, [close]); React.useEffect(() => { const tag = dismissTime === "never" ? null : typeof dismissTime === "number" ? window.setTimeout(() => closeHandler.current?.(), dismissTime) : window.setTimeout(() => closeHandler.current?.(), 5000); timerTag.current = tag; return () => { if (tag != null) { window.clearTimeout(tag); } }; }, [dismissTime]); const cancelTimer = (): void => { const { current: tag } = timerTag; if (tag != null) { window.clearTimeout(tag); } }; return (
{(() => { const { message } = alert; if (typeof message === "function") { const Message = message; return ; } else return convertI18nText(message, t); })()}
); }; const AlertHost: React.FC = () => { const [alerts, setAlerts] = React.useState([]); // react guarantee that state setters are stable, so we don't need to add it to dependency list React.useEffect(() => { const consume = (alert: AlertInfoEx): void => { setAlerts((old) => [...old, alert]); }; alertService.registerConsumer(consume); return () => { alertService.unregisterConsumer(consume); }; }, []); return (
{alerts.map((alert) => { return ( { setAlerts((old) => without(old, alert)); }} /> ); })}
); }; export default AlertHost;