Skip to content

Instantly share code, notes, and snippets.

@lenilsondc
Last active December 28, 2022 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lenilsondc/48d82c84d050e610bf94cd1c067cefa9 to your computer and use it in GitHub Desktop.
Save lenilsondc/48d82c84d050e610bf94cd1c067cefa9 to your computer and use it in GitHub Desktop.
Reducing screen complexity with composable wrappers
import { Button } from 'react-native';
import { compose } from './compose';
import { withLoadingOverlay } from './withLoadingOverlay';
import { useLoadingOverlay } from './useLoadingOverlay';
function ExampleView(){
const { showLoadingOverlay } = useLoadingOverlay();
return (
<>
<Button
title="Show loading"
onClick={() => showLoadingOverlay()}
/>
</>
);
}
const ExampleScreen = () => compose(
withLoadingOverlay(),
)(ExampleView)
export default ExampleScreen;
function compose<A>(): (arg: A) => A
function compose<A, B>(fn: (arg: A) => B): (arg: A) => B
function compose<A, B, C>(fn0: (arg: B) => C, fn1: (arg: A) => B): (arg: A) => C
function compose<A, B, C, D>(fn0: (arg: C) => D, fn1: (arg: B) => C, fn2: (arg: A) => B): (arg: A) => D
function compose<A, B, C, D, E>(fn0: (arg: D) => E, fn1: (arg: C) => D, fn2: (arg: B) => C, fn3: (arg: A) => B): (arg: A) => E
function compose<A, B, C, D, E, F>(fn0: (arg: E) => F, fn1: (arg: D) => E, fn2: (arg: C) => D, fn3: (arg: B) => C, fn4: (arg: A) => B): (arg: A) => F
function compose<A, B, C, D, E, F, G>(fn0: (arg: F) => G, fn1: (arg: E) => F, fn2: (arg: D) => E, fn3: (arg: C) => D, fn4: (arg: B) => C, fn5: (arg: A) => B): (arg: A) => G
function compose<A, B, C, D, E, F, G, H>(fn0: (arg: G) => H, fn1: (arg: F) => G, fn2: (arg: E) => F, fn3: (arg: D) => E, fn4: (arg: C) => D, fn5: (arg: B) => C, fn6: (arg: A) => B): (arg: A) => H
function compose<A, B, C, D, E, F, G, H, I>(fn0: (arg: H) => I, fn1: (arg: G) => H, fn2: (arg: F) => G, fn3: (arg: E) => F, fn4: (arg: D) => E, fn5: (arg: C) => D, fn6: (arg: B) => C, fn7: (arg: A) => B): (arg: A) => I
function compose(...fns: any[]): any {
return (initial: any) => fns.reduceRight((arg, fn) => fn(arg), initial);
}
export { compose };
import React, { useState, createContext } from 'react';
import { ActivityIndicator, View } from 'react-native';
type TLoadingOverlayContext = {
hideLoading(): void;
showLoading(): void;
};
export const LoadingOverlayContext = createContext<TLoadingOverlayContext>(
{} as TLoadingOverlayContext,
);
type LoadingProviderProps = {
children?: React.ReactNode;
};
export function LoadingProvider({ children }: LoadingProviderProps) {
const [visible, setVisible] = useState(false);
function showLoading() {
setVisible(true);
}
function hideLoading() {
setVisible(false);
}
function renderLoadingOverlay() {
return (
<View
style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center',
}}
>
<ActivityIndicator />
</View>
);
}
return (
<LoadingOverlayContext.Provider
value={{
hideLoading,
showLoading,
}}
>
{children}
{visible && renderLoadingOverlay()}
</LoadingOverlayContext.Provider>
);
}
import { useContext } from 'react';
import { LoadingOverlayContext } from './LoadingOverlayContext';
export function useLoadingOverlay() {
return useContext(LoadingOverlayContext);
}
import { withWrapper } from './withWrapper';
export const withLoadinOverlay = () => withWrapper(LoadingProvider);
import React, { ComponentType } from 'react';
export function withWrapper<TComponentProps extends JSX.IntrinsicAttributes>(
Wrapper: ComponentType,
) {
return (Component: ComponentType<TComponentProps>) =>
(props: TComponentProps) =>
(
<Wrapper>
<Component {...props} />
</Wrapper>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment