Files
dukang/apps/h5-partner/src/contexts/PartnerToastContext.tsx
T
2026-07-09 21:42:36 +08:00

54 lines
1.8 KiB
TypeScript

import { createContext, useCallback, useContext, useEffect, useRef, useState, type ReactNode } from 'react';
import { registerPartnerToastListener, type PartnerToastVariant } from '../lib/toast';
type PartnerToastContextValue = {
showToast: (message: string, variant?: PartnerToastVariant) => void;
};
const PartnerToastContext = createContext<PartnerToastContextValue | null>(null);
export function PartnerToastProvider({ children }: { children: ReactNode }) {
const [toast, setToast] = useState('');
const [variant, setVariant] = useState<PartnerToastVariant>('success');
const timerRef = useRef<number | null>(null);
const showToast = useCallback((message: string, nextVariant: PartnerToastVariant = 'success') => {
if (timerRef.current) window.clearTimeout(timerRef.current);
setVariant(nextVariant);
setToast(message);
timerRef.current = window.setTimeout(() => {
setToast('');
timerRef.current = null;
}, nextVariant === 'error' ? 3000 : 2000);
}, []);
useEffect(() => {
registerPartnerToastListener(showToast);
return () => {
registerPartnerToastListener(null);
if (timerRef.current) window.clearTimeout(timerRef.current);
};
}, [showToast]);
return (
<PartnerToastContext.Provider value={{ showToast }}>
{children}
{toast ? (
<div
className={`partner-toast${variant === 'error' ? ' partner-toast--error' : ''}`}
role="alert"
aria-live="assertive"
>
{toast}
</div>
) : null}
</PartnerToastContext.Provider>
);
}
export function usePartnerToast(): PartnerToastContextValue {
const ctx = useContext(PartnerToastContext);
if (!ctx) throw new Error('usePartnerToast 必须在 PartnerToastProvider 内使用');
return ctx;
}