diff --git a/database/useList.ts b/database/useList.ts index f5ba605..417c49e 100644 --- a/database/useList.ts +++ b/database/useList.ts @@ -109,7 +109,7 @@ const reducer = (state: ReducerState, action: ReducerAction): ReducerState => { } }; -export default (query: database.Query): ListHook => { +export default (query: database.Query | null | undefined): ListHook => { const [state, dispatch] = useReducer(reducer, initialState); const ref = useIsEqualRef(query, () => dispatch({ type: 'reset' })); @@ -138,7 +138,11 @@ export default (query: database.Query): ListHook => { useEffect( () => { - const query: database.Query = ref.current; + const query: database.Query | null | undefined = ref.current; + if (!query) { + dispatch({ type: 'value' }) + return; + } // This is here to indicate that all the data has been successfully received query.once( 'value', diff --git a/database/useListKeys.ts b/database/useListKeys.ts index 0068ba8..92a85ee 100644 --- a/database/useListKeys.ts +++ b/database/useListKeys.ts @@ -7,12 +7,11 @@ export type ListKeysHook = { value: string[]; }; -export default (query: database.Query): ListKeysHook => { +export default (query: database.Query | null | undefined): ListKeysHook => { const { error, loading, value } = useList(query); - // @ts-ignore return { error, loading, - value: value.map(snapshot => snapshot.key), + value: value.map(snapshot => snapshot.key as string), }; }; diff --git a/database/useListVals.ts b/database/useListVals.ts index dd7bfc2..ef952c6 100644 --- a/database/useListVals.ts +++ b/database/useListVals.ts @@ -8,7 +8,7 @@ export type ListValsHook = { }; export default ( - query: database.Query, + query: database.Query | null | undefined, keyField?: string ): ListValsHook => { const { error, loading, value } = useList(query); diff --git a/database/useObject.ts b/database/useObject.ts index 095b7c5..1f5bf4a 100644 --- a/database/useObject.ts +++ b/database/useObject.ts @@ -8,7 +8,7 @@ export type ObjectHook = { value?: database.DataSnapshot; }; -export default (query: database.Query): ObjectHook => { +export default (query: database.Query | null | undefined): ObjectHook => { const { error, loading, reset, setError, setValue, value } = useLoadingValue< database.DataSnapshot >(); @@ -17,6 +17,11 @@ export default (query: database.Query): ObjectHook => { useEffect( () => { const query = ref.current; + if (!query) { + setValue(null); + return; + } + query.on('value', setValue, setError); return () => { diff --git a/database/useObjectVal.ts b/database/useObjectVal.ts index 3ed8756..ae82243 100644 --- a/database/useObjectVal.ts +++ b/database/useObjectVal.ts @@ -7,7 +7,7 @@ export type ObjectValHook = { value?: T; }; -export default (query: database.Query): ObjectValHook => { +export default (query: database.Query | null | undefined): ObjectValHook => { const { error, loading, value } = useObject(query); return { error, diff --git a/firestore/useCollection.ts b/firestore/useCollection.ts index bf5fde9..f382484 100644 --- a/firestore/useCollection.ts +++ b/firestore/useCollection.ts @@ -9,7 +9,7 @@ export type CollectionHook = { }; export default ( - query: firestore.Query, + query: firestore.Query | null | undefined, options?: firestore.SnapshotListenOptions ): CollectionHook => { const { error, loading, reset, setError, setValue, value } = useLoadingValue< @@ -19,6 +19,7 @@ export default ( useEffect( () => { + if (!ref.current) return; const listener = options ? ref.current.onSnapshot(options, setValue, setError) : ref.current.onSnapshot(setValue, setError); diff --git a/firestore/useDocument.ts b/firestore/useDocument.ts index 8f02bf8..fc8ecb8 100644 --- a/firestore/useDocument.ts +++ b/firestore/useDocument.ts @@ -9,7 +9,7 @@ export type DocumentHook = { }; export default ( - docRef: firestore.DocumentReference, + docRef: firestore.DocumentReference | null | undefined, options?: firestore.SnapshotListenOptions ): DocumentHook => { const { error, loading, reset, setError, setValue, value } = useLoadingValue< @@ -19,6 +19,7 @@ export default ( useEffect( () => { + if (!ref.current) return; const listener = options ? ref.current.onSnapshot(options, setValue, setError) : ref.current.onSnapshot(setValue, setError); diff --git a/storage/useDownloadURL.ts b/storage/useDownloadURL.ts index fc07e85..f58f3f8 100644 --- a/storage/useDownloadURL.ts +++ b/storage/useDownloadURL.ts @@ -8,18 +8,20 @@ export type DownloadURLHook = { value?: string; }; -export default (storageRef: storage.Reference): DownloadURLHook => { +export default (storageRef: storage.Reference | null | undefined): DownloadURLHook => { const { error, loading, reset, setError, setValue, value } = useLoadingValue< string >(); - const ref = useComparatorRef( - storageRef, - (v1, v2) => v1.fullPath === v2.fullPath, - reset - ); + function isEqual(v1: storage.Reference | null | undefined, v2: storage.Reference | null | undefined): boolean { + const bothNull: boolean = !v1 && !v2; + const equal: boolean = !!v1 && !!v2 && v1.fullPath === v2.fullPath; + return bothNull || equal; + } + const ref = useComparatorRef(storageRef, isEqual, reset); useEffect( () => { + if (!ref.current) return; ref.current .getDownloadURL() .then(setValue) diff --git a/util/refHooks.ts b/util/refHooks.ts index 65a6bf9..d7f6a99 100644 --- a/util/refHooks.ts +++ b/util/refHooks.ts @@ -5,10 +5,10 @@ type RefHook = { }; export const useComparatorRef = ( - value: T, - isEqual: (v1: T, v2: T) => boolean, + value: T | null | undefined, + isEqual: (v1: T | null | undefined, v2: T | null | undefined) => boolean, onChange?: () => void -): RefHook => { +): RefHook => { const ref = useRef(value); useEffect(() => { if (!isEqual(value, ref.current)) { @@ -26,15 +26,20 @@ export interface HasIsEqual { } export const useIsEqualRef = >( - value: T, + value: T | null | undefined, onChange?: () => void -): RefHook => { - return useComparatorRef(value, (v1, v2) => v1.isEqual(v2), onChange); +): RefHook => { + function isEqual(v1: T | null | undefined, v2: T | null | undefined): boolean { + const bothNull: boolean = !v1 && !v2; + const equal: boolean = !!v1 && !!v2 && v1.isEqual(v2); + return bothNull || equal; + } + return useComparatorRef(value, isEqual, onChange); }; export const useIdentifyRef = ( - value: T, + value: T | null | undefined, onChange?: () => void -): RefHook => { +): RefHook => { return useComparatorRef(value, (v1, v2) => v1 === v2, onChange); };