@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
text/typescript
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,
};
};