import { FlashList, FlashListProps } from '@shopify/flash-list'; import { ForwardedRef, forwardRef, useCallback, useRef } from 'react'; import { FlatList, FlatListProps, RefreshControlProps } from 'react-native'; import RefreshControl from '../loader/RefreshControl'; import BottomSpacer from '../spacer/BottomSpacer'; type FactoryListProps = F extends true ? FlashListProps : FlatListProps; export type FactoryListRef = F extends true ? FlashList : FlatList; export type ListProps = Omit, keyof RefreshControlProps> & Partial & { inTabScreen?: boolean; flashed?: F; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any function List( { flashed, refreshing = false, onRefresh, ListFooterComponent, inTabScreen = false, ...props }: ListProps, ref: ForwardedRef>, ) { const Component = flashed ? FlashList : FlatList; const keyRef = useRef(null); const handleKeyExtractor = useCallback((item: T, index: number) => { // Use key if it exists if (keyRef.current) { return `${item[keyRef.current as keyof typeof item]}`; } // Find the key matching "id" in the first run if (keyRef.current === null) { let id = ''; for (const key in item) { const shorterId = id.isNotEmpty && key.length < id.length; if (key.match(/id/gi) && (shorterId || id.isEmpty)) { id = key; } } if (!id.isEmpty) { keyRef.current = id; return `${item[id as keyof typeof item]}`; } // If any key is not matched, always return the index keyRef.current = ''; } return `${index}`; }, []); if (flashed) { )} {...(!!onRefresh && { refreshControl: , })} ref={ref as ForwardedRef>} ListFooterComponent={ <> {ListFooterComponent} {inTabScreen && } } />; } return ( )} {...(!!onRefresh && { refreshControl: , })} ref={ref as ForwardedRef>} ListFooterComponent={ <> {ListFooterComponent} {inTabScreen && } } /> ); } export default forwardRef(List);