Skip to content
This repository was archived by the owner on Dec 3, 2022. It is now read-only.

Commit e49b66e

Browse files
committed
moved to Typescript
1 parent 497424d commit e49b66e

File tree

8 files changed

+374
-253
lines changed

8 files changed

+374
-253
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,3 @@ android/keystores/debug.keystore
5252
coverage/
5353
.jest/
5454
**/__snapshots__/**
55-

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
🏄‍♀️ Surfing the wave of React Hook hype with a few convenience hooks for `@react-navigation/core` v3. Destined to work on web, server, and React Native. Contributions welcome!
66

7-
87
## Examples (web only so far)
98

109
See an example web app which uses react-navigation and hooks on the client and the server:
@@ -82,9 +81,9 @@ function ReportNavigationEvents() {
8281
// prev state on evt.lastState
8382
// triggering navigation action on evt.action
8483

85-
setEvents(events => [...events, evt.type]);
86-
// evt.type is [will/did][Focus/Blur]
84+
setEvents(events => [...events, evt]);
8785
});
86+
// evt.type is [will/did][Focus/Blur]
8887
return (
8988
<>
9089
{events.map(evt => (

__mocks__/react.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Right now is not a way to trigger useEffect from Jest
2+
// see: https://github.com/facebook/react/issues/14050
3+
// TODO: Remove this module mock when solved
4+
import * as React from 'react';
5+
module.exports = { ...React, useEffect: React.useLayoutEffect };

dist/Hooks.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ function useNavigationEvents(handleEvt) {
3939
// identifies the nav object, then we should probably pass [navigation.state.key] here, to
4040
// make sure react doesn't needlessly detach and re-attach this effect. In practice this
4141
// seems to cause troubles
42-
undefined);
42+
undefined
43+
// [navigation.state.key]
44+
);
4345
}
4446
exports.useNavigationEvents = useNavigationEvents;
4547
var emptyFocusState = {
@@ -52,7 +54,9 @@ var didFocusState = tslib_1.__assign({}, emptyFocusState, { isFocused: true });
5254
var willBlurState = tslib_1.__assign({}, emptyFocusState, { isBlurring: true });
5355
var didBlurState = tslib_1.__assign({}, emptyFocusState, { isBlurred: true });
5456
var willFocusState = tslib_1.__assign({}, emptyFocusState, { isFocusing: true });
55-
var getInitialFocusState = function (isFocused) { return isFocused ? didFocusState : didBlurState; };
57+
var getInitialFocusState = function (isFocused) {
58+
return isFocused ? didFocusState : didBlurState;
59+
};
5660
function focusStateOfEvent(eventName) {
5761
switch (eventName) {
5862
case 'didFocus':

src/Hooks.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState, useContext, useEffect } from 'react';
22
import { NavigationContext } from '@react-navigation/core';
3-
// TODO: Remove "react-navigation-types-only" when https://github.com/react-navigation/react-navigation/pull/5276
3+
// TODO: move to "react-navigation" when https://github.com/react-navigation/react-navigation/pull/5276
44
// get merged
55
import {
66
NavigationScreenProp,
@@ -16,7 +16,7 @@ export function useNavigation<S>(): NavigationScreenProp<S & NavigationRoute> {
1616
}
1717

1818
export function useNavigationParam<T extends keyof NavigationParams>(
19-
paramName: T,
19+
paramName: T
2020
) {
2121
return useNavigation().getParam(paramName);
2222
}
@@ -50,7 +50,7 @@ export function useNavigationEvents(handleEvt: NavigationEventCallback) {
5050
// identifies the nav object, then we should probably pass [navigation.state.key] here, to
5151
// make sure react doesn't needlessly detach and re-attach this effect. In practice this
5252
// seems to cause troubles
53-
undefined,
53+
undefined
5454
// [navigation.state.key]
5555
);
5656
}
@@ -65,7 +65,8 @@ const didFocusState = { ...emptyFocusState, isFocused: true };
6565
const willBlurState = { ...emptyFocusState, isBlurring: true };
6666
const didBlurState = { ...emptyFocusState, isBlurred: true };
6767
const willFocusState = { ...emptyFocusState, isFocusing: true };
68-
const getInitialFocusState = (isFocused: boolean) => isFocused ? didFocusState : didBlurState;
68+
const getInitialFocusState = (isFocused: boolean) =>
69+
isFocused ? didFocusState : didBlurState;
6970
function focusStateOfEvent(eventName: EventType) {
7071
switch (eventName) {
7172
case 'didFocus':

src/__tests__/Hooks-test.tsx

Lines changed: 126 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,148 @@
1-
import * as React from 'react';
2-
import { View, Button } from 'react-native';
1+
import { default as React, useState } from 'react';
32
import * as renderer from 'react-test-renderer';
4-
import { createSwitchNavigator } from '@react-navigation/core';
3+
import {
4+
createSwitchNavigator,
5+
NavigationActions,
6+
} from '@react-navigation/core';
57
import { createAppContainer } from '@react-navigation/native';
8+
// TODO: move to "react-navigation" when https://github.com/react-navigation/react-navigation/pull/5276
9+
// get merged
10+
import { NavigationEventPayload } from 'react-navigation-types-only';
611

712
import {
8-
useNavigation
13+
useNavigation,
14+
useNavigationParam,
15+
useNavigationState,
16+
useNavigationKey,
17+
useNavigationEvents,
18+
useFocusState,
919
} from '../../dist/Hooks';
1020

1121
const HomeScreen = () => {
1222
const { navigate } = useNavigation();
13-
return <Button title="Go to Details" onPress={() => navigate('Details')} />;
14-
}
23+
return navigate('Details', { from: 'Home' });
24+
};
25+
26+
const DetailsScreen = () => {
27+
const from = useNavigationParam('from');
28+
return <p>{from}</p>;
29+
};
30+
31+
const OtherScreen = () => {
32+
const { routeName } = useNavigationState();
33+
return <p>{routeName}</p>;
34+
};
35+
36+
const KeyScreen = () => {
37+
const key = useNavigationKey();
38+
return <p>{key}</p>;
39+
};
1540

16-
const DetailsScreen = () => <View />;
41+
const EventScreen = () => {
42+
const [events, setEvents] = useState([] as NavigationEventPayload[]);
43+
useNavigationEvents((evt) => {
44+
// latest state on evt.state
45+
// prev state on evt.lastState
46+
// triggering navigation action on evt.action
47+
48+
setEvents(events => [...events, evt]);
49+
});
50+
// evt.type is [will/did][Focus/Blur]
51+
return (
52+
<>
53+
{events.map((evt, i) => (
54+
<p key={i}>{evt.type}</p>
55+
))}
56+
</>
57+
);
58+
};
59+
60+
const FocusScreen = () => (
61+
<p>{useFocusState().isFocused ? 'Focused' : 'Not Focused'}</p>
62+
);
1763

18-
const AppNavigator = createSwitchNavigator(
64+
const AppNavigator1 = createSwitchNavigator(
1965
{
20-
Home: HomeScreen,
21-
Details: DetailsScreen,
66+
Home: HomeScreen, // { nav: { "index": 0 ...
67+
Details: DetailsScreen, // { nav: { "index": 1 ...
68+
Other: OtherScreen, // { nav: { "index": 2 ...
2269
},
2370
{
2471
initialRouteName: 'Home',
72+
}
73+
);
74+
75+
const AppNavigator2 = createSwitchNavigator(
76+
{
77+
Other: OtherScreen,
78+
Key: KeyScreen,
79+
Event: EventScreen,
80+
Focus: FocusScreen,
2581
},
82+
{
83+
initialRouteName: 'Other',
84+
}
2685
);
2786

28-
const App = createAppContainer(AppNavigator);
87+
describe('AppNavigator1 Stack', () => {
88+
const App = createAppContainer(AppNavigator1);
89+
let navigationContainer;
90+
beforeEach(() => {
91+
navigationContainer = renderer.create(<App />);
92+
});
2993

30-
describe('Navigating to a new screen', () => {
31-
it('renders successfully', () => {
32-
const rendered = renderer.create(<App />);
33-
let tree = rendered.toJSON();
34-
expect(tree).toMatchSnapshot();
94+
it('useNavigation: Navigating to "DetailsScreen"', () => {
95+
const instance = navigationContainer.getInstance() as { state?: any };
96+
expect(instance.state.nav).toMatchObject({ index: 1 });
97+
});
3598

36-
// Manually trigger onPress
37-
//tree!.props.onPress();
38-
tree = rendered.toJSON();
99+
it('useNavigationParam: Get passed parameter', () => {
100+
const children = navigationContainer.toJSON().children;
101+
expect(children).toContain('Home');
102+
});
103+
104+
afterEach(() => {
105+
navigationContainer.unmount();
106+
});
107+
});
108+
109+
describe('AppNavigator2 Stack', () => {
110+
const App = createAppContainer(AppNavigator2);
111+
let navigationContainer;
112+
beforeEach(() => {
113+
navigationContainer = renderer.create(<App />);
114+
});
115+
116+
const eventTypes = ['willFocus', 'didFocus', 'willBlur', 'didBlur', 'action'];
117+
118+
it('usenNavigationState: Get current route name', () => {
119+
const children = navigationContainer.toJSON().children;
120+
expect(children).toContain('Other');
121+
});
122+
123+
it('usenNavigationKey: Get current key name', () => {
124+
const instance = navigationContainer.getInstance();
125+
instance.dispatch(NavigationActions.navigate({ routeName: 'Key' }));
126+
const children = navigationContainer.toJSON().children;
127+
expect(children).toContain('Key');
128+
});
129+
130+
it('useNavigationEvents: Get current subscribed events', () => {
131+
const instance = navigationContainer.getInstance();
132+
instance.dispatch(NavigationActions.navigate({ routeName: 'Event' }));
133+
const elems = navigationContainer.toJSON();
134+
expect(eventTypes).toContain(elems[0].children.toString());
135+
expect(eventTypes).toContain(elems[1].children.toString());
136+
});
137+
138+
it('useFocusState: Get focus state', () => {
139+
const instance = navigationContainer.getInstance();
140+
instance.dispatch(NavigationActions.navigate({ routeName: 'Focus' }));
141+
const children = navigationContainer.toJSON().children;
142+
expect(children).toContain('Focused');
143+
});
39144

40-
expect(rendered).toMatchSnapshot();
145+
afterEach(() => {
146+
navigationContainer.unmount();
41147
});
42148
});

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"compilerOptions": {
33
"target": "es5",
44
"module": "commonjs",
5-
"lib": ["es6"],
5+
"lib": ["es7"],
66
"jsx": "react",
77
"sourceMap": true,
88
"moduleResolution": "node",

0 commit comments

Comments
 (0)