All files / app/common/hoc createMappableInjectHoc.tsx

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63152x                       1120x     152x       78x           506x     506x 1103x     506x 1644x   1644x           1644x       1644x 356x     1288x   1288x     506x 506x     506x        
import React, { memo, useContext, useMemo, ComponentType, Context, FunctionComponent } from 'react';
import { Omit } from 'utility-types';
 
import { MatchedProps } from './InjectHoc';
import MappableInjectHoc, { MapToProps, MapToPropsFactory } from './MappableInjectHoc';
 
function isMapToPropsFactory<TContextProps, TMappedProps, TOwnProps>(
    mapToProps: (
        MapToProps<TContextProps, TMappedProps, TOwnProps> |
        MapToPropsFactory<TContextProps, TMappedProps, TOwnProps>
    )
): mapToProps is MapToPropsFactory<TContextProps, TMappedProps, TOwnProps> {
    return mapToProps.length === 0;
}
 
export default function createMappableInjectHoc<TContextProps>(
    ContextComponent: Context<TContextProps>,
    options?: { displayNamePrefix?: string }
): MappableInjectHoc<NonNullable<TContextProps>> {
    return <TMappedProps, TOwnProps>(
        mapToPropsOrFactory: (
            MapToProps<NonNullable<TContextProps>, TMappedProps, TOwnProps> |
            MapToPropsFactory<NonNullable<TContextProps>, TMappedProps, TOwnProps>
        )
    ) => {
        return <TProps extends MatchedProps<TMappedProps, TProps>>(
            OriginalComponent: ComponentType<TProps>
        ) => {
            const InnerDecoratedComponent: FunctionComponent<TProps> = memo(props =>
                <OriginalComponent { ...props } />
            );
 
            const DecoratedComponent: FunctionComponent<Omit<TProps, keyof TMappedProps>> = props => {
                const context = useContext(ContextComponent);
 
                const mapToProps = useMemo(() => (
                    isMapToPropsFactory(mapToPropsOrFactory) ?
                        mapToPropsOrFactory() :
                        mapToPropsOrFactory
                ), []);
 
                const mappedProps = context ?
                    mapToProps(context as NonNullable<TContextProps>, props as unknown as TOwnProps) :
                    context;
 
                if (!mappedProps) {
                    return null;
                }
 
                const mergedProps = { ...mappedProps, ...props } as unknown as TProps;
 
                return <InnerDecoratedComponent { ...mergedProps } />;
            };
 
            Eif (options && options.displayNamePrefix && OriginalComponent) {
                DecoratedComponent.displayName = `${options.displayNamePrefix}(${OriginalComponent.displayName || OriginalComponent.name})`;
            }
 
            return DecoratedComponent;
        };
    };
}