Skip to content

Instantly share code, notes, and snippets.

@Nicoolandgood
Created May 22, 2023 14:09
Show Gist options
  • Select an option

  • Save Nicoolandgood/a4f162f97eadd22c725dfa943de2de9f to your computer and use it in GitHub Desktop.

Select an option

Save Nicoolandgood/a4f162f97eadd22c725dfa943de2de9f to your computer and use it in GitHub Desktop.
Tiny Toast Provider for Primereact
function App() {
return (
<ToastProvider>
<Example />
</ToastProvider>
);
}
import { useEffect } from "react";
import { toast, useToast } from "./providers/ToastProvider";
const Example = () => {
const { show } = useToast();
useEffect(() => {
show({ detail: "My awesome toast from a hook !"});
// or...
toast.show({ detail: "My awesome toast from an import !"})
}, []);
return (
<>
My awesome content !
</>
)
};
import { createContext, PropsWithChildren, useContext, useLayoutEffect, useRef } from "react";
import { Toast, ToastMessage } from 'primereact/toast';
type MessageType = ToastMessage | ToastMessage[];
type ShowMessageFunction = (message: MessageType) => void;
interface ToastContextValue {
show: ShowMessageFunction;
showWarn: ShowMessageFunction;
showError: ShowMessageFunction;
showInfo: ShowMessageFunction;
showSuccess: ShowMessageFunction;
clear: () => void;
}
interface ToastProviderProps extends PropsWithChildren {}
const initialValue: ToastContextValue = {
show: () => null,
showWarn: () => null,
showError: () => null,
showInfo: () => null,
showSuccess: () => null,
clear: () => null,
}
const setSeverity = (message: MessageType, severity: string): MessageType => {
const isArray = Array.isArray(message);
return isArray? message.map(m => ({ ...m, severity: severity as any })): {...message, severity: severity as any};
};
export class ToastEvent extends Event {
constructor(
public message: MessageType,
) {
super("toast");
}
}
export const toast = new class Toaster {
private _currentEvent: ToastEvent | null = null;
show(message: MessageType) {
this._setCurrentEvent(message);
this._dispatchToast();
}
showSuccess(message: MessageType) {
this.show(setSeverity(message, 'success'));
}
showError(message: MessageType) {
this.show(setSeverity(message, 'error'));
}
showWarn(message: MessageType) {
this.show(setSeverity(message, 'warn'));
}
showInfo(message: MessageType) {
this.show(setSeverity(message, 'info'));
}
private _setCurrentEvent(message: MessageType) {
this._currentEvent = new ToastEvent(message);
}
private _dispatchToast() {
if(this._currentEvent)
window.dispatchEvent(this._currentEvent);
}
}
const ToastContext = createContext<ToastContextValue>(initialValue);
export const ToastProvider = (props: ToastProviderProps) => {
const toast = useRef<Toast>(null);
const show = (message: MessageType) => {
toast.current?.show(message);
}
useLayoutEffect(() => {
// Listening to toast events
const callback: any = (e: ToastEvent) => {
if (e instanceof ToastEvent)
show(e.message);
};
window.addEventListener("toast", callback);
return () => window.removeEventListener("toast", callback);
}, []);
const clear = () => toast.current?.clear();
const showSuccess = (message: MessageType) => show(setSeverity(message, 'success'));
const showInfo = (message: MessageType) => show(setSeverity(message, 'info'));
const showError = (message: MessageType) => show(setSeverity(message, 'error'));
const showWarn = (message: MessageType) => show(setSeverity(message, 'warn'));
return (
<>
<Toast ref={toast}/>
<ToastContext.Provider value={{
show, showError, showInfo, showSuccess, showWarn, clear,
}}>
{props.children}
</ToastContext.Provider>
</>
)
}
export const useToast = () => useContext(ToastContext);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment