56 lines
1.3 KiB
TypeScript
56 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { sse, type SseTopic } from "@/lib/sse";
|
|
|
|
type RealtimeRefreshProps = {
|
|
topic: SseTopic;
|
|
formId?: string;
|
|
debounceMs?: number;
|
|
};
|
|
|
|
export function RealtimeRefresh({
|
|
topic,
|
|
formId,
|
|
debounceMs = 150,
|
|
}: RealtimeRefreshProps) {
|
|
const router = useRouter();
|
|
const connectedOnce = useRef(false);
|
|
|
|
useEffect(() => {
|
|
connectedOnce.current = false;
|
|
let refreshTimer: ReturnType<typeof setTimeout> | undefined;
|
|
|
|
const refresh = () => {
|
|
if (refreshTimer) clearTimeout(refreshTimer);
|
|
refreshTimer = setTimeout(() => router.refresh(), debounceMs);
|
|
};
|
|
|
|
const onopen = () => {
|
|
if (connectedOnce.current) {
|
|
refresh();
|
|
} else {
|
|
connectedOnce.current = true;
|
|
}
|
|
};
|
|
|
|
const handleUpdate = (event: { formId: string }) => {
|
|
if (!formId || event.formId === formId) {
|
|
refresh();
|
|
}
|
|
};
|
|
|
|
const subscription = topic === "forms"
|
|
? sse.forms.sub("update", handleUpdate, { onopen })
|
|
: sse.submissions.sub("update", handleUpdate, { onopen });
|
|
|
|
return () => {
|
|
if (refreshTimer) clearTimeout(refreshTimer);
|
|
subscription.clean();
|
|
};
|
|
}, [debounceMs, formId, router, topic]);
|
|
|
|
return null;
|
|
}
|