The Node.js® Website
1import * as Toast from '@radix-ui/react-toast';
2import type {
3 Dispatch,
4 FC,
5 PropsWithChildren,
6 ReactNode,
7 SetStateAction,
8} from 'react';
9import { createContext, useEffect, useState } from 'react';
10
11import Notification from '@/components/Common/Notification';
12
13type NotificationContextType = {
14 message: string | ReactNode;
15 duration: number;
16} | null;
17
18type NotificationProps = { viewportClassName?: string };
19
20const NotificationContext = createContext<NotificationContextType>(null);
21
22export const NotificationDispatch = createContext<
23 Dispatch<SetStateAction<NotificationContextType>>
24>(() => {});
25
26export const NotificationProvider: FC<PropsWithChildren<NotificationProps>> = ({
27 viewportClassName,
28 children,
29}) => {
30 const [notification, dispatch] = useState<NotificationContextType>(null);
31
32 useEffect(() => {
33 const timeout = setTimeout(() => dispatch(null), notification?.duration);
34
35 return () => clearTimeout(timeout);
36 }, [notification]);
37
38 return (
39 <NotificationContext.Provider value={notification}>
40 <NotificationDispatch.Provider value={dispatch}>
41 <Toast.Provider>
42 {children}
43
44 <Toast.Viewport className={viewportClassName} />
45
46 {notification && (
47 <Notification duration={notification.duration}>
48 {notification.message}
49 </Notification>
50 )}
51 </Toast.Provider>
52 </NotificationDispatch.Provider>
53 </NotificationContext.Provider>
54 );
55};