Open
Description
I have a use case that make the use of useObject
quite painful.
It happens that the path of the Query
is depending on another request to the Database.
As conditional Hooks are forbidden I have to create every time another layer of Component to do the first query before I can use the secundary Component with your hook.
It would be great if query
can optionaly be a Promise<Query>
so I don't need this extra layer.
Example code :
import { useEffect, useMemo, useState } from 'react';
import { snapshotToData, ValOptions } from './helpers';
import { ObjectHook, ObjectValHook, Val } from './types';
import { useIsEqualRef, useLoadingValue } from '../util';
import { DataSnapshot, off, onValue, Query } from 'firebase/database';
function isPromise(p: any): p is Promise<Query | null | undefined> {
return typeof p === 'object' && typeof p['then'] === 'function';
}
export const useObject = (
query?: Query | null | Promise<Query | null | undefined>
): ObjectHook => {
const { error, loading, reset, setError, setValue, value } = useLoadingValue<
DataSnapshot,
Error
>();
const queryPromise: Promise<Query | null | undefined> = isPromise(query)
? query
: Promise.resolve(query);
const [resolved, setResolved] = useState(false);
const ref = useIsEqualRef<Query>(undefined, reset);
useEffect(() => {
if (!resolved) {
queryPromise.then((query) => {
ref.current = query;
setResolved(true);
});
return;
}
const effect = async () => {
const query = ref.current;
if (!query) {
setValue(undefined);
return;
}
onValue(query, setValue, setError);
return () => {
off(query, 'value', setValue);
};
};
effect();
}, [ref.current]);
const resArray: ObjectHook = [value, loading, error];
return useMemo(() => resArray, resArray);
};