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

Commit f7ff0c1

Browse files
authored
feat: add dangerouslyGetState (#63)
1 parent c0045d8 commit f7ff0c1

File tree

3 files changed

+49
-3
lines changed

3 files changed

+49
-3
lines changed

packages/core/src/__tests__/index.test.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import Screen from '../Screen';
44
import NavigationContainer from '../NavigationContainer';
55
import useNavigationBuilder from '../useNavigationBuilder';
66
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
7+
import useNavigation from '../useNavigation';
8+
import { NavigationState } from '../types';
79

810
beforeEach(() => (MockRouterKey.current = 0));
911

@@ -467,6 +469,7 @@ it('updates route params with setParams applied to parent', () => {
467469
{ key: 'foo', name: 'foo', params: { username: 'alice' } },
468470
{ key: 'bar', name: 'bar' },
469471
],
472+
stale: false,
470473
});
471474

472475
act(() => setParams({ age: 25 }));
@@ -480,6 +483,7 @@ it('updates route params with setParams applied to parent', () => {
480483
{ key: 'foo', name: 'foo', params: { username: 'alice', age: 25 } },
481484
{ key: 'bar', name: 'bar' },
482485
],
486+
stale: false,
483487
});
484488
});
485489

@@ -519,6 +523,40 @@ it('handles change in route names', () => {
519523
});
520524
});
521525

526+
it('gives access to internal state', () => {
527+
const TestNavigator = (props: any): any => {
528+
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
529+
530+
return descriptors[state.routes[state.index].key].render();
531+
};
532+
533+
let state: NavigationState | undefined;
534+
535+
const Test = () => {
536+
const navigation = useNavigation();
537+
state = navigation.dangerouslyGetState();
538+
return null;
539+
};
540+
541+
const root = (
542+
<NavigationContainer>
543+
<TestNavigator initialRouteName="bar">
544+
<Screen name="bar" component={Test} />
545+
</TestNavigator>
546+
</NavigationContainer>
547+
);
548+
549+
render(root).update(root);
550+
551+
expect(state).toEqual({
552+
index: 0,
553+
key: '0',
554+
routeNames: ['bar'],
555+
routes: [{ key: 'bar', name: 'bar' }],
556+
stale: false,
557+
});
558+
});
559+
522560
it("throws if navigator doesn't have any screens", () => {
523561
const TestNavigator = (props: any) => {
524562
useNavigationBuilder(MockRouter, props);

packages/core/src/types.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,13 @@ export type NavigationProp<
377377
dangerouslyGetParent():
378378
| NavigationProp<ParamListBase, string, any, any>
379379
| undefined;
380+
381+
/**
382+
* Returns the navigator's state. Reason why the function is called
383+
* dangerouslyGetState is to discourage developers to use internal navigation's state.
384+
* Note that this method doesn't re-render screen when the result changes. So don't use it in `render`.
385+
*/
386+
dangerouslyGetState(): State;
380387
} & EventConsumer<EventMap & EventMapBase> &
381388
PrivateValueStore<ParamList, RouteName, EventMap>;
382389

packages/core/src/useNavigationCache.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,19 @@ export default function useNavigationCache<
4343
// Cache object which holds navigation objects for each screen
4444
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
4545
// In reality, these deps will rarely change, if ever
46+
const parentNavigation = React.useContext(NavigationContext);
47+
4648
const cache = React.useMemo(
4749
() => ({ current: {} as NavigationCache<State, ScreenOptions> }),
4850
// eslint-disable-next-line react-hooks/exhaustive-deps
49-
[getState, navigation, setOptions, router, emitter]
51+
[getState, navigation, setOptions, router, emitter, parentNavigation]
5052
);
5153

5254
const actions = {
5355
...router.actionCreators,
5456
...BaseActions,
5557
};
5658

57-
const parentNavigation = React.useContext(NavigationContext);
58-
5959
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
6060
(acc, route, index) => {
6161
const previous = cache.current[route.key];
@@ -92,6 +92,7 @@ export default function useNavigationCache<
9292
...helpers,
9393
...emitter.create(route.key),
9494
dangerouslyGetParent: () => parentNavigation,
95+
dangerouslyGetState: getState as () => State,
9596
dispatch,
9697
setOptions: (options: object) =>
9798
setOptions(o => ({

0 commit comments

Comments
 (0)