forked from react-navigation/hooks
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHooks.ts
More file actions
100 lines (91 loc) · 2.9 KB
/
Hooks.ts
File metadata and controls
100 lines (91 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { useState, useContext, useEffect } from 'react';
import {
NavigationContext,
NavigationScreenProp,
NavigationRoute,
NavigationParams,
NavigationEventCallback,
NavigationEventPayload,
EventType,
} from 'react-navigation';
export function useNavigation<S>(): NavigationScreenProp<S & NavigationRoute> {
return useContext(NavigationContext as any);
}
export function useNavigationParam<T extends keyof NavigationParams>(
paramName: T
) {
return useNavigation().getParam(paramName);
}
export function useNavigationState() {
return useNavigation().state;
}
export function useNavigationKey() {
return useNavigation().state.key;
}
export function useNavigationEvents(handleEvt: NavigationEventCallback) {
const navigation = useNavigation();
useEffect(
() => {
if (!navigation) {
return;
}
const subsA = navigation.addListener(
'action' as any // TODO should we remove it? it's not in the published typedefs
, handleEvt);
const subsWF = navigation.addListener('willFocus', handleEvt);
const subsDF = navigation.addListener('didFocus', handleEvt);
const subsWB = navigation.addListener('willBlur', handleEvt);
const subsDB = navigation.addListener('didBlur', handleEvt);
return () => {
subsA.remove();
subsWF.remove();
subsDF.remove();
subsWB.remove();
subsDB.remove();
};
},
// For TODO consideration: If the events are tied to the navigation object and the key
// identifies the nav object, then we should probably pass [navigation.state.key] here, to
// make sure react doesn't needlessly detach and re-attach this effect. In practice this
// seems to cause troubles
undefined
// [navigation.state.key]
);
}
const emptyFocusState = {
isFocused: false,
isBlurring: false,
isBlurred: false,
isFocusing: false,
};
const didFocusState = { ...emptyFocusState, isFocused: true };
const willBlurState = { ...emptyFocusState, isBlurring: true };
const didBlurState = { ...emptyFocusState, isBlurred: true };
const willFocusState = { ...emptyFocusState, isFocusing: true };
const getInitialFocusState = (isFocused: boolean) =>
isFocused ? didFocusState : didBlurState;
function focusStateOfEvent(eventName: EventType) {
switch (eventName) {
case 'didFocus':
return didFocusState;
case 'willFocus':
return willFocusState;
case 'willBlur':
return willBlurState;
case 'didBlur':
return didBlurState;
default:
return null;
}
}
export function useFocusState() {
const navigation = useNavigation();
const isFocused = navigation.isFocused();
const [focusState, setFocusState] = useState(getInitialFocusState(isFocused));
function handleEvt(e: NavigationEventPayload) {
const newState = focusStateOfEvent(e.type);
newState && setFocusState(newState);
}
useNavigationEvents(handleEvt);
return focusState;
}