nice
This commit is contained in:
50
app/useAsyncState.ts
Normal file
50
app/useAsyncState.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { onMounted, onServerPrefetch, useSSRContext, shallowRef, type ShallowRef } from 'vue';
|
||||
|
||||
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 = useSSRContext<{ registry: Record<string, unknown> }>();
|
||||
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 };
|
||||
}
|
||||
Reference in New Issue
Block a user