import { use } from 'foxact/use';
import { useSyncExternalStore } from 'react';
import type { LiveData } from './livedata';
function noopSubscribe() {
return () => {};
}
function nullGetSnapshot() {
return null;
}
function undefinedGetSnapshot() {
return undefined;
}
/**
* subscribe LiveData and return the value.
*/
export function useLiveData | null | undefined>(
liveData: Input
): NonNullable extends LiveData
? Input extends undefined
? T | undefined
: Input extends null
? T | null
: T
: never {
return useSyncExternalStore(
liveData ? liveData.reactSubscribe : noopSubscribe,
liveData
? liveData.reactGetSnapshot
: liveData === undefined
? undefinedGetSnapshot
: nullGetSnapshot
);
}
/**
* subscribe LiveData and return the value. If the value is nullish, will suspends until the value is not nullish.
*/
export function useEnsureLiveData(liveData$: LiveData): NonNullable {
const data = useLiveData(liveData$);
if (data === null || data === undefined) {
return use(
new Promise((resolve, reject) => {
const subscription = liveData$.subscribe({
next(value) {
if (value === null || value === undefined) {
resolve(value);
subscription.unsubscribe();
}
},
error(err) {
reject(err);
},
complete() {
reject(new Error('Unexpected completion'));
},
});
})
);
}
return data;
}