1
1
import {
2
2
useState ,
3
3
useContext ,
4
+ useEffect ,
4
5
useLayoutEffect ,
5
6
useRef ,
6
7
useCallback ,
@@ -15,6 +16,7 @@ import {
15
16
NavigationEventPayload ,
16
17
EventType ,
17
18
} from 'react-navigation' ;
19
+ import { BackHandler } from 'react-native' ;
18
20
19
21
export function useNavigation < S > ( ) : NavigationScreenProp < S & NavigationRoute > {
20
22
const navigation = useContext ( NavigationContext ) as any ; // TODO typing?
@@ -143,3 +145,76 @@ export function useFocusState() {
143
145
144
146
return focusState ;
145
147
}
148
+
149
+
150
+ type EffectCallback = ( ( ) => void ) | ( ( ) => ( ) => void ) ;
151
+
152
+ // Inspired by same hook from react-navigation v5
153
+ // See https://github.com/react-navigation/hooks/issues/39#issuecomment-534694135
154
+ export const useFocusEffect = ( callback : EffectCallback ) => {
155
+ const navigation = useNavigation ( ) ;
156
+ const getCallback = useGetter ( callback ) ;
157
+
158
+ useEffect ( ( ) => {
159
+ let isFocused = false ;
160
+ let cleanup : ( ( ) => void ) | void ;
161
+
162
+ if ( navigation . isFocused ( ) ) {
163
+ cleanup = getCallback ( ) ( ) ;
164
+ isFocused = true ;
165
+ }
166
+
167
+ const focusSubscription = navigation . addListener ( 'willFocus' , ( ) => {
168
+ // If callback was already called for focus, avoid calling it again
169
+ // The focus event may also fire on intial render, so we guard against runing the effect twice
170
+ if ( isFocused ) {
171
+ return ;
172
+ }
173
+
174
+ cleanup && cleanup ( ) ;
175
+ cleanup = getCallback ( ) ( ) ;
176
+ isFocused = true ;
177
+ } ) ;
178
+
179
+ const blurSubscription = navigation . addListener ( 'willBlur' , ( ) => {
180
+ cleanup && cleanup ( ) ;
181
+ cleanup = undefined ;
182
+ isFocused = false ;
183
+ } ) ;
184
+
185
+ return ( ) => {
186
+ cleanup && cleanup ( ) ;
187
+ focusSubscription . remove ( ) ;
188
+ blurSubscription . remove ( ) ;
189
+ } ;
190
+ } , [ getCallback , navigation ] ) ;
191
+ } ;
192
+
193
+ export const useIsFocused = ( ) => {
194
+ const navigation = useNavigation ( ) ;
195
+ const [ focused , setFocused ] = useState ( navigation . isFocused ( ) ) ;
196
+
197
+ useEffect ( ( ) => {
198
+ const focusSubscription = navigation . addListener ( 'willFocus' , ( ) =>
199
+ setFocused ( true ) ,
200
+ ) ;
201
+ const blurSubscription = navigation . addListener ( 'willBlur' , ( ) =>
202
+ setFocused ( false ) ,
203
+ ) ;
204
+ return ( ) => {
205
+ focusSubscription . remove ( ) ;
206
+ blurSubscription . remove ( ) ;
207
+ } ;
208
+ } , [ setFocused ] ) ;
209
+
210
+ return focused ;
211
+ } ;
212
+
213
+ export const useBackHandler = ( backHandler : ( ) => boolean ) => {
214
+ useFocusEffect ( ( ) => {
215
+ BackHandler . addEventListener ( 'hardwareBackPress' , backHandler ) ;
216
+ return ( ) => {
217
+ BackHandler . removeEventListener ( 'hardwareBackPress' , backHandler ) ;
218
+ } ;
219
+ } ) ;
220
+ } ;
0 commit comments