feat: add screenListeners prop on navigators similar to screenOptions

This commit is contained in:
Satyajit Sahoo
2021-05-26 00:35:34 +02:00
parent aa77f0618b
commit cde44a5785
9 changed files with 81 additions and 19 deletions

View File

@@ -20,14 +20,25 @@ declare global {
type Keyof<T extends {}> = Extract<keyof T, string>;
export type DefaultNavigatorOptions<
ParamList extends ParamListBase,
State extends NavigationState,
ScreenOptions extends {},
ParamList extends ParamListBase = ParamListBase
EventMap extends EventMapBase
> = DefaultRouterOptions<Keyof<ParamList>> & {
/**
* Children React Elements to extract the route configuration from.
* Only `Screen`, `Group` and `React.Fragment` are supported as children.
*/
children: React.ReactNode;
/**
* Event listeners for all the screens in the navigator.
*/
screenListeners?:
| ScreenListeners<State, EventMap>
| ((props: {
route: RouteProp<ParamList>;
navigation: any;
}) => ScreenListeners<State, EventMap>);
/**
* Default options for all screens under this navigator.
*/
@@ -564,9 +575,9 @@ export type TypedNavigator<
Navigator: React.ComponentType<
Omit<
React.ComponentProps<Navigator>,
keyof DefaultNavigatorOptions<any, any>
keyof DefaultNavigatorOptions<any, any, any, any>
> &
DefaultNavigatorOptions<ScreenOptions, ParamList>
DefaultNavigatorOptions<ParamList, State, ScreenOptions, EventMap>
>;
/**
* Component used for grouping multiple route configuration.

View File

@@ -202,7 +202,13 @@ export default function useNavigationBuilder<
EventMap extends Record<string, any>
>(
createRouter: RouterFactory<State, any, RouterOptions>,
options: DefaultNavigatorOptions<ScreenOptions> & RouterOptions
options: DefaultNavigatorOptions<
ParamListBase,
State,
ScreenOptions,
EventMap
> &
RouterOptions
) {
const navigatorKey = useRegisterNavigator();
@@ -210,7 +216,7 @@ export default function useNavigationBuilder<
| NavigatorRoute<State>
| undefined;
const { children, ...rest } = options;
const { children, screenListeners, ...rest } = options;
const { current: router } = React.useRef<Router<State, any>>(
createRouter({
...((rest as unknown) as RouterOptions),
@@ -487,8 +493,14 @@ export default function useNavigationBuilder<
const listeners = ([] as (((e: any) => void) | undefined)[])
.concat(
...routeNames.map((name) => {
const { listeners } = screens[name][1];
// Get an array of listeners for all screens + common listeners on navigator
...[
screenListeners,
...routeNames.map((name) => {
const { listeners } = screens[name][1];
return listeners;
}),
].map((listeners) => {
const map =
typeof listeners === 'function'
? listeners({ route: route as any, navigation })
@@ -501,6 +513,8 @@ export default function useNavigationBuilder<
: undefined;
})
)
// We don't want same listener to be called multiple times for same event
// So we remove any duplicate functions from the array
.filter((cb, i, self) => cb && self.lastIndexOf(cb) === i);
listeners.forEach((listener) => listener?.(e));