UNPKG

@taraai/read-write

Version:

Synchronous NoSQL/Firestore for React

63 lines (50 loc) 1.9 kB
import filter from 'lodash/filter'; import isEqual from 'lodash/isEqual'; import some from 'lodash/some'; import { useRef, useEffect } from 'react'; import useFirestore from '../redux-firebase/useFirestore'; import { getQueryName } from '../utils/query'; import useCache from './useCache'; const getChanges = (data = [], prevData = []) => { const result = {}; result.added = filter(data, (d) => !some(prevData, (p) => isEqual(d, p))); result.removed = filter(prevData, (p) => !some(data, (d) => isEqual(p, d))); return result; }; export default function useRead(queries, selection = null) { const firestore = useFirestore(); const firestoreIsEnabled = !!firestore; const queryRef = useRef(); const aliasRef = useRef(); useEffect(() => { const queryArray = Array.isArray(queries) ? queries : [queries]; if (!firestoreIsEnabled || isEqual(queryArray, queryRef.current)) return; const changes = getChanges(queryArray, queryRef.current); queryRef.current = queryArray; aliasRef.current = queryRef.current.map(getQueryName); // Remove listeners for inactive subscriptions firestore.unsetListeners(changes.removed); // Add listeners for new subscriptions firestore.setListeners(changes.added); }, [aliasRef.current]); // clean up for hot-reloads and mount/unmount useEffect( () => () => { if (!firestoreIsEnabled || !queryRef.current) return; queryRef.current = []; aliasRef.current = undefined; firestore.unsetListeners && firestore.unsetListeners(queryRef.current); }, [], ); // All data from firestore is standard JSON except Timestamps if (selection === '::alias') { return Array.isArray(queries) ? queries.map(getQueryName) : getQueryName(queries); } return useCache( Array.isArray(queries) ? queries.map(getQueryName) : getQueryName(queries), selection, ); }