snort/packages/app/src/Hooks/useRequestBuilder.tsx

47 lines
1.3 KiB
TypeScript

import { useSyncExternalStore } from "react";
import { RequestBuilder, System } from "System";
import { EmptySnapshot, NoteStore, StoreSnapshot } from "System/NoteCollection";
import { unwrap } from "Util";
const useRequestBuilder = <TStore extends NoteStore, TSnapshot = ReturnType<TStore["getSnapshotData"]>>(
type: { new (): TStore },
rb: RequestBuilder | null,
debounced?: number
) => {
const subscribe = (onChanged: () => void) => {
const store = System.Query<TStore>(type, rb);
let t: ReturnType<typeof setTimeout> | undefined;
const release = store.hook(() => {
if (!t) {
t = setTimeout(() => {
clearTimeout(t);
t = undefined;
onChanged();
}, debounced ?? 500);
}
});
return () => {
if (rb?.id) {
System.CancelQuery(rb.id);
}
release();
};
};
const getState = (): StoreSnapshot<TSnapshot> => {
if (rb?.id) {
const q = System.GetQuery(rb.id);
if (q) {
return unwrap(q).feed?.snapshot as StoreSnapshot<TSnapshot>;
}
}
return EmptySnapshot as StoreSnapshot<TSnapshot>;
};
return useSyncExternalStore<StoreSnapshot<TSnapshot>>(
v => subscribe(v),
() => getState()
);
};
export default useRequestBuilder;