(query?: Query | null)
| 15 | import { ListHook, ListKeysHook, ListValsHook, Val } from './types'; |
| 16 | |
| 17 | export const useList = (query?: Query | null): ListHook => { |
| 18 | const [state, dispatch] = useListReducer(); |
| 19 | |
| 20 | const queryRef = useIsEqualRef(query, () => dispatch({ type: 'reset' })); |
| 21 | const ref: Query | null | undefined = queryRef.current; |
| 22 | |
| 23 | useEffect(() => { |
| 24 | if (!ref) { |
| 25 | dispatch({ type: 'empty' }); |
| 26 | return; |
| 27 | } |
| 28 | |
| 29 | const onChildAdded = ( |
| 30 | snapshot: DataSnapshot | null, |
| 31 | previousKey?: string | null |
| 32 | ) => { |
| 33 | dispatch({ type: 'add', previousKey, snapshot }); |
| 34 | }; |
| 35 | |
| 36 | const onChildChanged = (snapshot: DataSnapshot | null) => { |
| 37 | dispatch({ type: 'change', snapshot }); |
| 38 | }; |
| 39 | |
| 40 | const onChildMoved = ( |
| 41 | snapshot: DataSnapshot | null, |
| 42 | previousKey?: string | null |
| 43 | ) => { |
| 44 | dispatch({ type: 'move', previousKey, snapshot }); |
| 45 | }; |
| 46 | |
| 47 | const onChildRemoved = (snapshot: DataSnapshot | null) => { |
| 48 | dispatch({ type: 'remove', snapshot }); |
| 49 | }; |
| 50 | |
| 51 | const onError = (error: Error) => { |
| 52 | dispatch({ type: 'error', error }); |
| 53 | }; |
| 54 | |
| 55 | const onValue = (snapshots: DataSnapshot[] | null) => { |
| 56 | dispatch({ type: 'value', snapshots }); |
| 57 | }; |
| 58 | |
| 59 | let childAddedHandler: ReturnType<typeof firebaseOnChildAdded> | undefined; |
| 60 | const onInitialLoad = (snapshot: DataSnapshot) => { |
| 61 | const snapshotVal = snapshot.val(); |
| 62 | let childrenToProcess = snapshotVal |
| 63 | ? Object.keys(snapshot.val()).length |
| 64 | : 0; |
| 65 | |
| 66 | // If the list is empty then initialise the hook and use the default `onChildAdded` behaviour |
| 67 | if (childrenToProcess === 0) { |
| 68 | childAddedHandler = firebaseOnChildAdded(ref, onChildAdded, onError); |
| 69 | onValue([]); |
| 70 | } else { |
| 71 | // Otherwise, we load the first batch of children all to reduce re-renders |
| 72 | const children: DataSnapshot[] = []; |
| 73 | |
| 74 | const onChildAddedWithoutInitialLoad = ( |
no test coverage detected