UNPKG

@applicaster/zapp-react-native-ui-components

Version:

Applicaster Zapp React Native ui components for the Quick Brick App

90 lines (72 loc) 2.45 kB
import * as React from "react"; import * as R from "ramda"; const allTrue = R.all(R.equals(true)); const anyFalse = R.any(R.equals(false)); const anyTrue = R.any(R.equals(true)); const reducer = (state, { payload }) => { if (!R.isNil(payload) && !state[payload]) { return R.set(R.lensIndex(payload), true)(state); } return state; }; type Return = { isAnyLoading: boolean; isAllLoaded: boolean; waitForAllComponents: boolean; onLoadFinished: (index: number) => void; onLoadFailed: ({ error, index }: { error: Error; index: number }) => void; shouldShowLoadingError: boolean; isAnyLoaded: boolean; arePreviousComponentsLoaded: (index: number) => boolean; }; type Action = { payload: { index: number } }; type Loaded = true; type Loading = false; type LoadingState = Array<Loaded | Loading>; // TODO: Take this value from Zapp configuration, when feature is added to GeneralScreen const SHOULD_FAIL_ON_COMPONENT_LOADING = false; export const useLoadingState = (count: number): Return => { const [loadingError, setLoadingError] = React.useState(null); const [componentsState, dispatch] = React.useReducer< React.Reducer<LoadingState, Action> >(reducer, new Array(count).fill(false)); const handleComponentLoaded = React.useCallback((index) => { dispatch({ payload: index }); }, []); const handleComponentLoadErrorWhenNeedToFail = React.useCallback( ({ error }) => { if (error !== loadingError) { setLoadingError(error); } }, [] ); const handleComponentLoadErrorWhenNoNeedToFail = React.useCallback( ({ index }) => { handleComponentLoaded(index); }, [] ); const arePreviousComponentsLoaded = React.useCallback( (index) => { if (index === 0) { return true; } const componentsBefore = R.slice(0, index, componentsState); return allTrue(componentsBefore); }, [componentsState] ); return { isAnyLoading: anyFalse(componentsState), isAllLoaded: allTrue(componentsState), onLoadFinished: handleComponentLoaded, onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING ? handleComponentLoadErrorWhenNeedToFail : handleComponentLoadErrorWhenNoNeedToFail, shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError, isAnyLoaded: anyTrue(componentsState), waitForAllComponents: SHOULD_FAIL_ON_COMPONENT_LOADING, arePreviousComponentsLoaded, }; };