Skip to content
This repository was archived by the owner on Feb 8, 2020. It is now read-only.

Commit 8134895

Browse files
committed
fix: use correct dispatch in methods in screen's navigation prop
1 parent 9625689 commit 8134895

File tree

4 files changed

+60
-40
lines changed

4 files changed

+60
-40
lines changed

packages/core/src/useDescriptors.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
NavigationState,
1414
ParamListBase,
1515
RouteConfig,
16+
Router,
1617
} from './types';
1718

1819
type Options<ScreenOptions extends object> = {
@@ -29,6 +30,7 @@ type Options<ScreenOptions extends object> = {
2930
addActionListener: (listener: ChildActionListener) => void;
3031
removeActionListener: (listener: ChildActionListener) => void;
3132
onRouteFocus: (key: string) => void;
33+
router: Router<NavigationState, NavigationAction>;
3234
emitter: NavigationEventEmitter;
3335
};
3436

@@ -54,6 +56,7 @@ export default function useDescriptors<
5456
addActionListener,
5557
removeActionListener,
5658
onRouteFocus,
59+
router,
5760
emitter,
5861
}: Options<ScreenOptions>) {
5962
const [options, setOptions] = React.useState<{ [key: string]: object }>({});
@@ -79,6 +82,7 @@ export default function useDescriptors<
7982
getState,
8083
navigation,
8184
setOptions,
85+
router,
8286
emitter,
8387
});
8488

packages/core/src/useNavigationBuilder.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ export default function useNavigationBuilder<
233233
onRouteFocus,
234234
addActionListener,
235235
removeActionListener,
236+
router,
236237
emitter,
237238
});
238239

packages/core/src/useNavigationCache.tsx

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import * as React from 'react';
2+
import * as BaseActions from './BaseActions';
23
import { NavigationEventEmitter } from './useEventEmitter';
34
import {
45
NavigationAction,
56
NavigationHelpers,
67
NavigationProp,
78
ParamListBase,
89
NavigationState,
10+
Router,
911
} from './types';
1012

1113
type Options = {
1214
state: NavigationState;
1315
getState: () => NavigationState;
14-
navigation: NavigationHelpers<ParamListBase>;
16+
navigation: NavigationHelpers<ParamListBase> &
17+
Partial<NavigationProp<ParamListBase, string, any, any, any>>;
1518
setOptions: (
1619
cb: (options: { [key: string]: object }) => { [key: string]: object }
1720
) => void;
21+
router: Router<NavigationState, NavigationAction>;
1822
emitter: NavigationEventEmitter;
1923
};
2024

@@ -33,16 +37,21 @@ type NavigationCache<
3337
export default function useNavigationCache<
3438
State extends NavigationState,
3539
ScreenOptions extends object
36-
>({ state, getState, navigation, setOptions, emitter }: Options) {
40+
>({ state, getState, navigation, setOptions, router, emitter }: Options) {
3741
// Cache object which holds navigation objects for each screen
3842
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
3943
// In reality, these deps will rarely change, if ever
4044
const cache = React.useMemo(
4145
() => ({ current: {} as NavigationCache<State, ScreenOptions> }),
4246
// eslint-disable-next-line react-hooks/exhaustive-deps
43-
[getState, navigation, setOptions, emitter]
47+
[getState, navigation, setOptions, router, emitter]
4448
);
4549

50+
const actions = {
51+
...router.actionCreators,
52+
...BaseActions,
53+
};
54+
4655
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
4756
(acc, route, index) => {
4857
const previous = cache.current[route.key];
@@ -56,19 +65,29 @@ export default function useNavigationCache<
5665
// eslint-disable-next-line @typescript-eslint/no-unused-vars
5766
const { emit, ...rest } = navigation;
5867

68+
const dispatch = (
69+
action: NavigationAction | ((state: State) => State)
70+
) =>
71+
navigation.dispatch(
72+
typeof action === 'object' && action != null
73+
? { source: route.key, ...action }
74+
: action
75+
);
76+
77+
const helpers = Object.keys(actions).reduce(
78+
(acc, name) => {
79+
// @ts-ignore
80+
acc[name] = (...args: any) => dispatch(actions[name](...args));
81+
return acc;
82+
},
83+
{} as { [key: string]: () => void }
84+
);
85+
5986
acc[route.key] = {
6087
...rest,
88+
...helpers,
6189
...emitter.create(route.key),
62-
dispatch: (
63-
action:
64-
| NavigationAction
65-
| ((state: NavigationState) => NavigationState)
66-
) =>
67-
navigation.dispatch(
68-
typeof action === 'object' && action != null
69-
? { source: route.key, ...action }
70-
: action
71-
),
90+
dispatch,
7291
setOptions: (options: object) =>
7392
setOptions(o => ({
7493
...o,
@@ -86,7 +105,7 @@ export default function useNavigationCache<
86105
return navigation ? navigation.isFocused() : true;
87106
},
88107
isFirstRouteInParent: () => isFirst,
89-
} as NavigationProp<ParamListBase, string, State, ScreenOptions>;
108+
};
90109
}
91110

92111
return acc;

packages/core/src/useNavigationHelpers.tsx

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,30 @@ import {
1212
Router,
1313
} from './types';
1414

15-
type Options<Action extends NavigationAction> = {
15+
type Options<State extends NavigationState, Action extends NavigationAction> = {
1616
onAction: (
1717
action: NavigationAction,
1818
visitedNavigators?: Set<string>
1919
) => boolean;
20-
getState: () => NavigationState;
21-
setState: (state: NavigationState) => void;
20+
getState: () => State;
21+
setState: (state: State) => void;
2222
emitter: NavigationEventEmitter;
23-
router: Router<NavigationState, Action>;
23+
router: Router<State, Action>;
2424
};
2525

2626
/**
2727
* Navigation object with helper methods to be used by a navigator.
2828
* This object includes methods for common actions as well as methods the parent screen's navigation object.
2929
*/
30-
export default function useNavigationHelpers<Action extends NavigationAction>({
31-
onAction,
32-
getState,
33-
setState,
34-
emitter,
35-
router,
36-
}: Options<Action>) {
30+
export default function useNavigationHelpers<
31+
State extends NavigationState,
32+
Action extends NavigationAction
33+
>({ onAction, getState, setState, emitter, router }: Options<State, Action>) {
3734
const parentNavigationHelpers = React.useContext(NavigationContext);
3835
const { performTransaction } = React.useContext(NavigationStateContext);
3936

40-
return React.useMemo((): NavigationHelpers<ParamListBase> &
41-
Partial<NavigationProp<ParamListBase, string, any, any, any>> => {
42-
const dispatch = (
43-
action: NavigationAction | ((state: NavigationState) => NavigationState)
44-
) => {
37+
return React.useMemo(() => {
38+
const dispatch = (action: Action | ((state: State) => State)) => {
4539
performTransaction(() => {
4640
if (typeof action === 'function') {
4741
setState(action(getState()));
@@ -56,17 +50,18 @@ export default function useNavigationHelpers<Action extends NavigationAction>({
5650
...BaseActions,
5751
};
5852

59-
// @ts-ignore
53+
const helpers = Object.keys(actions).reduce(
54+
(acc, name) => {
55+
// @ts-ignore
56+
acc[name] = (...args: any) => dispatch(actions[name](...args));
57+
return acc;
58+
},
59+
{} as { [key: string]: () => void }
60+
);
61+
6062
return {
6163
...parentNavigationHelpers,
62-
...Object.keys(actions).reduce(
63-
(acc, name) => {
64-
// @ts-ignore
65-
acc[name] = (...args: any) => dispatch(actions[name](...args));
66-
return acc;
67-
},
68-
{} as { [key: string]: () => void }
69-
),
64+
...helpers,
7065
dispatch,
7166
emit: emitter.emit,
7267
isFocused: parentNavigationHelpers
@@ -76,7 +71,8 @@ export default function useNavigationHelpers<Action extends NavigationAction>({
7671
router.canGoBack(getState()) ||
7772
(parentNavigationHelpers && parentNavigationHelpers.canGoBack()) ||
7873
false,
79-
};
74+
} as NavigationHelpers<ParamListBase> &
75+
(NavigationProp<ParamListBase, string, any, any, any> | undefined);
8076
}, [
8177
router,
8278
getState,

0 commit comments

Comments
 (0)