Files
djledda-web/app/useAsyncState.ts
Daniel Ledda 7539e6ed48 updatge
2024-11-01 15:42:09 +01:00

56 lines
1.6 KiB
TypeScript

import { onMounted, onServerPrefetch, type ShallowRef, shallowRef } from "vue";
import useDJSSRContext from "@/useDJSSRContext.ts";
declare global {
// deno-lint-ignore no-var
var appstate: Partial<Record<string, unknown>>;
}
export default function useAsyncState<T>(
key: string,
getter: (context: { hostUrl: string }) => Promise<T | null>,
options?: { suspensible: boolean },
): { result: ShallowRef<T | null>; stateIsReady: Promise<unknown> } {
const ssrContext = useDJSSRContext();
const isClient = typeof ssrContext === "undefined";
const registry = ssrContext?.registry ?? globalThis?.appstate;
const hostUrl = isClient ? globalThis.location.origin : "http://localhost:8080";
const state = shallowRef<T | null>(null);
let resolve = () => {};
const promise = new Promise<void>((res) => {
resolve = res;
});
if (key in registry) {
state.value = registry[key] as T;
delete registry[key];
resolve();
} else {
if (!isClient) {
resolve();
}
onServerPrefetch(async () => {
const result = await getter({ hostUrl });
registry[key] = result;
state.value = result;
});
if (options?.suspensible ?? true) {
getter({ hostUrl }).then((result) => {
state.value = result;
resolve();
}).catch(resolve);
} else {
onMounted(async () => {
state.value = await getter({ hostUrl });
resolve();
});
}
}
return { result: state, stateIsReady: promise };
}