52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
/**
|
|
* Boilerplate-killer for the Layer-3 realtime hooks.
|
|
*
|
|
* Every `use-X-realtime` hook used to repeat this same shape:
|
|
*
|
|
* const ws = useWSClient();
|
|
* const wsId = useWorkspaceStore(s => s.currentWorkspaceId);
|
|
* useEffect(() => {
|
|
* if (!ws || !wsId) return;
|
|
* const unsubs = [ ws.on(...), ws.on(...), ws.onReconnect(...) ];
|
|
* return () => { for (const u of unsubs) u(); };
|
|
* }, [ws, wsId, ...]);
|
|
*
|
|
* `useWSSubscriptions(setup, deps)` collapses the lifecycle scaffolding so
|
|
* each hook focuses on its actual subscription list. The `setup` callback
|
|
* runs only when both ws + wsId are non-null, receives them as args, and
|
|
* returns the array of unsubs to wire into cleanup.
|
|
*
|
|
* Per-record hooks pass their record id via the deps array (so it
|
|
* re-subscribes when navigating between records). They can also access
|
|
* other narrow-scoped values via closure from the calling component.
|
|
*/
|
|
import { useEffect } from "react";
|
|
import type { WSClient } from "@/data/realtime/ws-client";
|
|
import { useWSClient } from "@/data/realtime/realtime-provider";
|
|
import { useWorkspaceStore } from "@/data/workspace-store";
|
|
|
|
export type WSSubscriptionSetup = (
|
|
ws: WSClient,
|
|
wsId: string,
|
|
) => (() => void)[] | undefined;
|
|
|
|
export function useWSSubscriptions(
|
|
setup: WSSubscriptionSetup,
|
|
deps: readonly unknown[],
|
|
) {
|
|
const ws = useWSClient();
|
|
const wsId = useWorkspaceStore((s) => s.currentWorkspaceId);
|
|
|
|
useEffect(() => {
|
|
if (!ws || !wsId) return;
|
|
const unsubs = setup(ws, wsId) ?? [];
|
|
return () => {
|
|
for (const u of unsubs) u();
|
|
};
|
|
// setup is intentionally NOT in deps — callers control re-subscription
|
|
// via the explicit `deps` array. Putting setup in deps would re-fire
|
|
// on every render (closures), defeating the whole point.
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [ws, wsId, ...deps]);
|
|
}
|