Skip to content

Commit

Permalink
draft fix of issue 10527
Browse files Browse the repository at this point in the history
- sorry for all the failing tests and lint issues
  • Loading branch information
Doris Ward committed May 17, 2022
1 parent 4c2b69f commit 492e2a0
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 120 deletions.
34 changes: 15 additions & 19 deletions packages/core/src/BaseNavigationContainer.tsx
Expand Up @@ -25,7 +25,6 @@ import type {
NavigationContainerRef,
} from './types';
import UnhandledActionContext from './UnhandledActionContext';
import useChildListeners from './useChildListeners';
import useEventEmitter from './useEventEmitter';
import useKeyedChildListeners from './useKeyedChildListeners';
import useOptionsGetters from './useOptionsGetters';
Expand Down Expand Up @@ -103,38 +102,35 @@ const BaseNavigationContainer = React.forwardRef(
const isFirstMountRef = React.useRef<boolean>(true);

const navigatorKeyRef = React.useRef<string | undefined>();

const getKey = React.useCallback(() => navigatorKeyRef.current, []);

const setKey = React.useCallback((key: string) => {
navigatorKeyRef.current = key;
}, []);

const { listeners, addListener } = useChildListeners();

const { keyedListeners, addKeyedListener } = useKeyedChildListeners();

const focusListeners = [...keyedListeners.focus.values()];
const dispatch = React.useCallback(
(
action:
| NavigationAction
| ((state: NavigationState) => NavigationAction)
) => {
if (listeners.focus[0] == null) {
if (focusListeners[0] == null) {
console.error(NOT_INITIALIZED_ERROR);
} else {
listeners.focus[0]((navigation) => navigation.dispatch(action));
focusListeners[0]((navigation) => navigation.dispatch(action));
}
},
[listeners.focus]
[keyedListeners.focus]
);

const canGoBack = React.useCallback(() => {
if (listeners.focus[0] == null) {
if (focusListeners[0] == null) {
return false;
}

const { result, handled } = listeners.focus[0]((navigation) =>
const { result, handled } = focusListeners[0]((navigation) =>
navigation.canGoBack()
);

Expand All @@ -143,28 +139,29 @@ const BaseNavigationContainer = React.forwardRef(
} else {
return false;
}
}, [listeners.focus]);
}, [keyedListeners.focus]);

const resetRoot = React.useCallback(
(state?: PartialState<NavigationState> | NavigationState) => {
const target = state?.key ?? keyedListeners.getState.root?.().key;
const target =
state?.key ?? keyedListeners.getState.get('root')?.().key;

if (target == null) {
console.error(NOT_INITIALIZED_ERROR);
} else {
listeners.focus[0]((navigation) =>
focusListeners[0]?.((navigation) =>
navigation.dispatch({
...CommonActions.reset(state),
target,
})
);
}
},
[keyedListeners.getState, listeners.focus]
[keyedListeners.getState, keyedListeners.focus]
);

const getRootState = React.useCallback(() => {
return keyedListeners.getState.root?.();
return keyedListeners.getState.get('root')?.();
}, [keyedListeners.getState]);

const getCurrentRoute = React.useCallback(() => {
Expand Down Expand Up @@ -201,7 +198,7 @@ const BaseNavigationContainer = React.forwardRef(
getRootState,
getCurrentRoute,
getCurrentOptions,
isReady: () => listeners.focus[0] != null,
isReady: () => focusListeners[0] != null,
}),
[
canGoBack,
Expand All @@ -210,7 +207,7 @@ const BaseNavigationContainer = React.forwardRef(
getCurrentOptions,
getCurrentRoute,
getRootState,
listeners.focus,
keyedListeners.focus,
resetRoot,
]
);
Expand Down Expand Up @@ -249,13 +246,12 @@ const BaseNavigationContainer = React.forwardRef(

const builderContext = React.useMemo(
() => ({
addListener,
addKeyedListener,
onDispatchAction,
onOptionsChange,
stackRef,
}),
[addListener, addKeyedListener, onDispatchAction, onOptionsChange]
[addKeyedListener, onDispatchAction, onOptionsChange]
);

const scheduleContext = React.useMemo(
Expand Down
19 changes: 6 additions & 13 deletions packages/core/src/NavigationBuilderContext.tsx
Expand Up @@ -7,25 +7,19 @@ import * as React from 'react';

import type { NavigationHelpers } from './types';

export type ListenerMap = {
action: ChildActionListener;
focus: FocusedNavigationListener;
};
export type MapValueType<A> = A extends Map<any, infer V> ? V : never;

export type KeyedListenerMap = {
getState: GetStateListener;
beforeRemove: ChildBeforeRemoveListener;
getState: Map<string, GetStateListener>;
beforeRemove: Map<string, ChildBeforeRemoveListener>;
action: Map<string, ChildActionListener>;
focus: Map<string, FocusedNavigationListener>;
};

export type AddListener = <T extends keyof ListenerMap>(
type: T,
listener: ListenerMap[T]
) => void;

export type AddKeyedListener = <T extends keyof KeyedListenerMap>(
type: T,
key: string,
listener: KeyedListenerMap[T]
listener: MapValueType<KeyedListenerMap[T]> | undefined
) => void;

export type ChildActionListener = (
Expand Down Expand Up @@ -56,7 +50,6 @@ const NavigationBuilderContext = React.createContext<{
action: NavigationAction,
visitedNavigators?: Set<string>
) => boolean;
addListener?: AddListener;
addKeyedListener?: AddKeyedListener;
onRouteFocus?: (key: string) => void;
onDispatchAction: (action: NavigationAction, noop: boolean) => void;
Expand Down
35 changes: 0 additions & 35 deletions packages/core/src/useChildListeners.tsx

This file was deleted.

5 changes: 0 additions & 5 deletions packages/core/src/useDescriptors.tsx
Expand Up @@ -8,7 +8,6 @@ import * as React from 'react';

import NavigationBuilderContext, {
AddKeyedListener,
AddListener,
} from './NavigationBuilderContext';
import NavigationContext from './NavigationContext';
import NavigationRouteContext from './NavigationRouteContext';
Expand Down Expand Up @@ -64,7 +63,6 @@ type Options<
onAction: (action: NavigationAction) => boolean;
getState: () => State;
setState: (state: State) => void;
addListener: AddListener;
addKeyedListener: AddKeyedListener;
onRouteFocus: (key: string) => void;
router: Router<State, NavigationAction>;
Expand Down Expand Up @@ -93,7 +91,6 @@ export default function useDescriptors<
onAction,
getState,
setState,
addListener,
addKeyedListener,
onRouteFocus,
router,
Expand All @@ -108,7 +105,6 @@ export default function useDescriptors<
() => ({
navigation,
onAction,
addListener,
addKeyedListener,
onRouteFocus,
onDispatchAction,
Expand All @@ -118,7 +114,6 @@ export default function useDescriptors<
[
navigation,
onAction,
addListener,
addKeyedListener,
onRouteFocus,
onDispatchAction,
Expand Down
25 changes: 17 additions & 8 deletions packages/core/src/useFocusedListenersChildrenAdapter.tsx
Expand Up @@ -9,7 +9,10 @@ import type { NavigationHelpers } from './types';

type Options = {
navigation: NavigationHelpers<ParamListBase>;
focusedListeners: FocusedNavigationListener[];
focusedListeners: Map<
string | undefined,
FocusedNavigationListener | undefined
>;
};

/**
Expand All @@ -19,16 +22,22 @@ export default function useFocusedListenersChildrenAdapter({
navigation,
focusedListeners,
}: Options) {
const { addListener } = React.useContext(NavigationBuilderContext);
const { addKeyedListener } = React.useContext(NavigationBuilderContext);

let listenerKey = 'undefined';
const listener = React.useCallback(
(callback: FocusedNavigationCallback<any>) => {
if (navigation.isFocused()) {
for (const listener of focusedListeners) {
const { handled, result } = listener(callback);
const listenerKeys = focusedListeners.keys();
for (const key of listenerKeys) {
const listener = focusedListeners.get(key);
if (listener) {
const { handled, result } = listener(callback);

if (handled) {
return { handled, result };
if (handled) {
listenerKey = key ?? 'undefined';
return { handled, result };
}
}
}

Expand All @@ -41,7 +50,7 @@ export default function useFocusedListenersChildrenAdapter({
);

React.useEffect(
() => addListener?.('focus', listener),
[addListener, listener]
() => addKeyedListener?.('focus', listenerKey, listener),
[addKeyedListener, listenerKey, listener]
);
}
38 changes: 23 additions & 15 deletions packages/core/src/useKeyedChildListeners.tsx
@@ -1,31 +1,39 @@
import * as React from 'react';

import type { KeyedListenerMap } from './NavigationBuilderContext';
import type {
KeyedListenerMap,
MapValueType,
} from './NavigationBuilderContext';

type KeyedChildListeners = {
[ListenerType in keyof KeyedListenerMap]: Map<
string | undefined,
MapValueType<KeyedListenerMap[ListenerType]> | undefined
>;
};

/**
* Hook which lets child navigators add getters to be called for obtaining rehydrated state.
*/
export default function useKeyedChildListeners() {
const { current: keyedListeners } = React.useRef<{
[K in keyof KeyedListenerMap]: Record<
string,
KeyedListenerMap[K] | undefined
>;
}>({
getState: {},
beforeRemove: {},
const { current: keyedListeners } = React.useRef<KeyedChildListeners>({
getState: new Map(),
beforeRemove: new Map(),
action: new Map(),
focus: new Map(),
});

const addKeyedListener = React.useCallback(
<T extends keyof KeyedListenerMap>(
type: T,
key: string,
listener: KeyedListenerMap[T]
<ListenerType extends keyof KeyedChildListeners>(
type: ListenerType,
key: string | undefined,
listener: MapValueType<KeyedListenerMap[ListenerType]> | undefined
) => {
keyedListeners[type][key] = listener;
const keyToSet = key !== undefined ? key : 'undefined';
keyedListeners[type].set(keyToSet, listener as any);

return () => {
keyedListeners[type][key] = undefined;
keyedListeners[type].set(keyToSet, undefined);
};
},
[keyedListeners]
Expand Down
8 changes: 2 additions & 6 deletions packages/core/src/useNavigationBuilder.tsx
Expand Up @@ -28,7 +28,6 @@ import {
PrivateValueStore,
RouteConfig,
} from './types';
import useChildListeners from './useChildListeners';
import useComponent from './useComponent';
import useCurrentRender from './useCurrentRender';
import useDescriptors, { ScreenConfigWithParent } from './useDescriptors';
Expand Down Expand Up @@ -613,16 +612,14 @@ export default function useNavigationBuilder<
emitter.emit({ type: 'state', data: { state } });
}, [emitter, state]);

const { listeners: childListeners, addListener } = useChildListeners();

const { keyedListeners, addKeyedListener } = useKeyedChildListeners();

const onAction = useOnAction({
router,
getState,
setState,
key: route?.key,
actionListeners: childListeners.action,
actionListeners: keyedListeners.action,
beforeRemoveListeners: keyedListeners.beforeRemove,
routerConfigOptions: {
routeNames,
Expand Down Expand Up @@ -654,7 +651,7 @@ export default function useNavigationBuilder<

useFocusedListenersChildrenAdapter({
navigation,
focusedListeners: childListeners.focus,
focusedListeners: keyedListeners.focus,
});

useOnGetState({
Expand All @@ -677,7 +674,6 @@ export default function useNavigationBuilder<
getState,
setState,
onRouteFocus,
addListener,
addKeyedListener,
router,
// @ts-expect-error: this should have both core and custom events, but too much work right now
Expand Down

0 comments on commit 492e2a0

Please sign in to comment.