I am trying to implement a react hook that allows me to generate a toast of the Blueprint JS library (version 5.7.2) at any time. The code I wrote is as follows:
import {
createContext,
useCallback,
useContext,
useEffect,
useState,
} from "react";
import type { OverlayToasterProps, ToastProps } from "@blueprintjs/core";
import { OverlayToaster, Position } from "@blueprintjs/core";
import { createRoot } from "react-dom/client";
import { v4 } from "uuid";
function createToaster(
props?: OverlayToasterProps,
container = document.body,
): Promise<NotificationCtx> {
const containerElement = document.createElement("div");
container.appendChild(containerElement);
const root = createRoot(containerElement);
return new Promise<NotificationCtx>((resolve, reject) => {
root.render(
<OverlayToaster
{...props}
usePortal={false}
ref={(toaster) => {
if (toaster) {
resolve({
show: (toast: ToastProps, key?: string) => {
return toaster.show(toast, key ?? v4());
},
dismiss: (key: string) => {
toaster.dismiss(key);
},
});
} else {
reject(new Error("Toaster is null"));
}
}}
/>,
);
});
}
export interface NotificationCtx {
dismiss: (key: string) => void;
show: (toast: ToastProps, key?: string) => string;
}
const INITIAL_CONTEXT = {
show: () => "",
dismiss: () => null,
};
const NotificationContext = createContext<NotificationCtx>(INITIAL_CONTEXT);
export function NotificationProvider(p: { children: JSX.Element }) {
const [toaster, setToaster] = useState<NotificationCtx>(INITIAL_CONTEXT);
useEffect(() => {
createToaster({
position: Position.TOP_RIGHT,
}).then((t) => {
setToaster(t);
});
}, []);
return (
<NotificationContext.Provider value={toaster}>
{p.children}
</NotificationContext.Provider>
);
}
export function useNotifications(): NotificationCtx {
return useContext(NotificationContext);
}
In another component I render to the screen by writing:
const notification = useNotifications();
notification.show(
{
message: "Hello world!",
intent: "success",
icon: "tick",
},
);
The result is that at the end of rendering the page I see the toast 2 times.
Where am I going wrong?