import * as React from "react"; import * as R from "ramda"; import { View, ViewStyle } from "react-native"; import { platformSelect } from "../../reactUtils"; type Data = Array; type RenderItemProps = { index: number } & Record; export const useSequentialRenderItem = (data: Data) => { const [componentsState, dispatch] = React.useReducer( (state, { data, type }) => { if (state[data]) { return state; } switch (type) { case "set": return R.set(R.lensIndex(data), true)(state); case "reset": return data; default: return state; } }, new Array(data.length).fill(false) ); React.useLayoutEffect(() => { dispatch({ type: "reset", data: new Array(data.length).fill(false) }); }, [data]); const arePreviousComponentsReady = React.useCallback( (index) => R.compose(R.all(R.equals(true)), R.take(index))(componentsState), [componentsState] ); const onLoadFinished = React.useCallback((id) => { dispatch({ type: "set", data: id }); }, []); const renderItem = React.useCallback( R.curry( // eslint-disable-next-line react/display-name (renderItem, props: RenderItemProps) => { const { index, item } = props; const readyToDisplay = index === 0 ? true : arePreviousComponentsReady(index); const displayStyle: ViewStyle = { display: readyToDisplay ? "flex" : "none", }; const readyStyle = { visibility: readyToDisplay ? "visible" : "hidden", } as ViewStyle; const style = platformSelect({ tvos: readyStyle, samsung_tv: readyStyle, lg_tv: readyStyle, default: displayStyle, }); const shouldRenderEmptyIfNotReady = platformSelect({ tvos: true, samsung_tv: true, lg_tv: true, default: false, }); if (!readyToDisplay && shouldRenderEmptyIfNotReady) { return ; } return ( {renderItem({ ...props, onLoadFinished: () => { onLoadFinished(index); }, })} ); } ), [componentsState, arePreviousComponentsReady, onLoadFinished] ); return { renderItem, allLoaded: R.all(R.equals(true), componentsState), componentsState, }; };