react-firehooks
Version:
Lightweight dependency-free collection of React hooks for Firebase
36 lines (35 loc) • 1.92 kB
JavaScript
import { useEffect, useMemo, useRef } from "react";
import { useMultiLoadingValue } from "./useMultiLoadingValue.js";
/**
* @internal
*/
export function useMultiListen(references, onChange, isEqualRef) {
const { states, setError, setLoading, setValue } = useMultiLoadingValue(references.length);
const prevReferences = useRef([]);
const subscriptions = useRef([]);
useEffect(() => {
var _a, _b;
// unsubscribe and shorten `subscriptions` if number of references was reduced
subscriptions.current.slice(references.length).forEach((unsubscribe) => unsubscribe());
subscriptions.current = subscriptions.current.slice(0, references.length);
// shorten `prevReferences` size if number of references was reduced
prevReferences.current = prevReferences.current.slice(0, references.length);
// subscribe to new references and unsubscribe to changed references
const changedReferences = references
.map((ref, refIndex) => [ref, refIndex])
.filter(([ref, refIndex]) => !isEqualRef(ref, prevReferences.current[refIndex]));
for (const [ref, refIndex] of changedReferences) {
(_b = (_a = subscriptions.current)[refIndex]) === null || _b === void 0 ? void 0 : _b.call(_a);
prevReferences.current[refIndex] = ref;
setLoading(refIndex);
subscriptions.current[refIndex] = onChange(ref, (snap) => setValue(refIndex, snap), (error) => setError(refIndex, error));
}
}, [references, isEqualRef, onChange, setError, setLoading, setValue]);
// unsubscribe and cleanup on unmount
useEffect(() => () => {
subscriptions.current.forEach((unsubscribe) => unsubscribe());
subscriptions.current = [];
prevReferences.current = [];
}, []);
return useMemo(() => states.map((state) => [state.value, state.loading, state.error]), [states]);
}