feat: add withNavigation and withNavigationFocus

This commit is contained in:
satyajit.happy
2019-09-17 17:57:01 +02:00
parent b4bbf9b0c3
commit 114a5dc888
7 changed files with 118 additions and 14 deletions

View File

@@ -7,15 +7,18 @@ import {
import ScreenPropsContext from './ScreenPropsContext';
import createCompatNavigationProp from './createCompatNavigationProp';
type Props = {
navigation: NavigationProp<ParamListBase>;
route: RouteProp<ParamListBase, string>;
type Props<ParamList extends ParamListBase> = {
navigation: NavigationProp<ParamList>;
route: RouteProp<ParamList, string>;
component: React.ComponentType<any>;
};
function ScreenComponent(props: Props) {
function ScreenComponent<ParamList extends ParamListBase>(
props: Props<ParamList>
) {
const navigation = React.useMemo(
() => createCompatNavigationProp(props.navigation, props.route),
() =>
createCompatNavigationProp(props.navigation as any, props.route as any),
[props.navigation, props.route]
);

View File

@@ -6,6 +6,7 @@ import {
RouteProp,
} from '@react-navigation/core';
import * as helpers from './helpers';
import { CompatNavigationProp } from './types';
type EventName = 'willFocus' | 'willBlur' | 'didFocus' | 'didBlur' | 'refocus';
@@ -14,16 +15,21 @@ const blurSubscriptions = new WeakMap<() => void, () => void>();
const refocusSubscriptions = new WeakMap<() => void, () => void>();
export default function createCompatNavigationProp<
ParamList extends ParamListBase
NavigationPropType extends NavigationProp<ParamListBase>,
ParamList extends ParamListBase = NavigationPropType extends NavigationProp<
infer P
>
? P
: ParamListBase
>(
navigation: NavigationProp<ParamList>,
navigation: NavigationPropType,
state:
| (RouteProp<ParamList, keyof ParamList> & {
state?: NavigationState | PartialState<NavigationState>;
})
| NavigationState
| PartialState<NavigationState>
) {
): CompatNavigationProp<NavigationPropType> {
return {
...navigation,
...Object.entries(helpers).reduce<{
@@ -179,5 +185,5 @@ export default function createCompatNavigationProp<
return undefined;
},
};
} as any;
}

View File

@@ -80,7 +80,7 @@ export default function createCompatNavigatorFactory<
navigation,
route,
}: {
navigation: NavigationProp<ParamList>;
navigation: NavigationPropType;
route: RouteProp<ParamList, keyof ParamList> & {
state?: NavigationState | PartialState<NavigationState>;
};
@@ -101,10 +101,9 @@ export default function createCompatNavigatorFactory<
typeof routeNavigationOptions === 'function' ||
typeof screenNavigationOptions === 'function'
? {
navigation: createCompatNavigationProp<ParamList>(
navigation,
route
),
navigation: createCompatNavigationProp<
NavigationPropType
>(navigation, route),
navigationOptions: defaultNavigationOptions || {},
screenProps,
}

View File

@@ -9,4 +9,12 @@ export {
default as createCompatNavigatorFactory,
} from './createCompatNavigatorFactory';
export {
default as createCompatNavigationProp,
} from './createCompatNavigationProp';
export { default as useCompatNavigation } from './useCompatNavigation';
export { default as withNavigation } from './withNavigation';
export { default as withNavigationFocus } from './withNavigationFocus';
export * from './types';

View File

@@ -0,0 +1,25 @@
import * as React from 'react';
import {
useNavigation,
useRoute,
NavigationProp,
ParamListBase,
} from '@react-navigation/core';
import createCompatNavigationProp from './createCompatNavigationProp';
import { CompatNavigationProp } from './types';
export default function useCompatNavigation<
T extends NavigationProp<ParamListBase>
>() {
const navigation = useNavigation();
const route = useRoute();
return React.useMemo(
() =>
createCompatNavigationProp(
navigation,
route as any
) as CompatNavigationProp<T>,
[navigation, route]
);
}

View File

@@ -0,0 +1,33 @@
import * as React from 'react';
import { NavigationProp, ParamListBase } from '@react-navigation/core';
import useCompatNavigation from './useCompatNavigation';
import { CompatNavigationProp } from './types';
type InjectedProps<T extends NavigationProp<ParamListBase>> = {
navigation: CompatNavigationProp<T>;
};
export default function withNavigation<
T extends NavigationProp<ParamListBase>,
P extends InjectedProps<T>,
C extends React.ComponentType<P>
>(Comp: C) {
const WrappedComponent = ({
onRef,
...rest
}: Exclude<P, InjectedProps<T>> & {
onRef?: C extends React.ComponentClass<any>
? React.Ref<InstanceType<C>>
: never;
}): React.ReactElement => {
const navigation = useCompatNavigation<T>();
// @ts-ignore
return <Comp ref={onRef} navigation={navigation} {...rest} />;
};
WrappedComponent.displayName = `withNavigation(${Comp.displayName ||
Comp.name})`;
return WrappedComponent;
}

View File

@@ -0,0 +1,30 @@
import * as React from 'react';
import { useIsFocused } from '@react-navigation/core';
type InjectedProps = {
isFocused: boolean;
};
export default function withNavigationFocus<
P extends InjectedProps,
C extends React.ComponentType<P>
>(Comp: C) {
const WrappedComponent = ({
onRef,
...rest
}: Exclude<P, InjectedProps> & {
onRef?: C extends React.ComponentClass<any>
? React.Ref<InstanceType<C>>
: never;
}): React.ReactElement => {
const isFocused = useIsFocused();
// @ts-ignore
return <Comp ref={onRef} isFocused={isFocused} {...rest} />;
};
WrappedComponent.displayName = `withNavigationFocus(${Comp.displayName ||
Comp.name})`;
return WrappedComponent;
}