Files
sass-mohfarawati/components/root/query-toast-bridge.tsx
T

85 lines
2.0 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { toast } from "sonner";
const TOAST_PARAM_NAMES = ["success", "error"] as const;
const PENDING_TOAST_STORAGE_KEY = "mohfarawati-pending-toast";
export function QueryToastBridge() {
const pathname = usePathname();
const router = useRouter();
const searchParams = useSearchParams();
const handledKeyRef = useRef<string | null>(null);
useEffect(() => {
const rawToast = window.sessionStorage.getItem(PENDING_TOAST_STORAGE_KEY);
if (!rawToast) {
return;
}
try {
const pendingToast = JSON.parse(rawToast) as {
message?: string;
type?: "success" | "error";
};
if (!pendingToast.message) {
return;
}
if (pendingToast.type === "error") {
toast.error(pendingToast.message);
} else if (pendingToast.type === "success") {
toast.success(pendingToast.message);
} else {
toast(pendingToast.message);
}
} finally {
window.sessionStorage.removeItem(PENDING_TOAST_STORAGE_KEY);
}
}, [pathname]);
useEffect(() => {
const successMessage = searchParams.get("success");
const errorMessage = searchParams.get("error");
if (!successMessage && !errorMessage) {
handledKeyRef.current = null;
return;
}
const handledKey = `${pathname}:${successMessage ?? ""}:${errorMessage ?? ""}`;
if (handledKeyRef.current === handledKey) {
return;
}
handledKeyRef.current = handledKey;
if (successMessage) {
toast.success(successMessage);
}
if (errorMessage) {
toast.error(errorMessage);
}
const nextParams = new URLSearchParams(searchParams.toString());
for (const name of TOAST_PARAM_NAMES) {
nextParams.delete(name);
}
const nextQuery = nextParams.toString();
router.replace(nextQuery ? `${pathname}?${nextQuery}` : pathname, {
scroll: false,
});
}, [pathname, router, searchParams]);
return null;
}