1
1
/* @flow strict-local */
2
2
3
+ import React from 'react' ;
4
+ import { AppState } from 'react-native' ;
5
+ import type { AppStateValues } from 'react-native/Libraries/AppState/AppState' ;
3
6
// eslint-disable-next-line id-match
4
7
import type { ____ViewStyle_Internal } from 'react-native/Libraries/StyleSheet/StyleSheetTypes' ;
5
8
9
+ import * as logging from './utils/logging' ;
6
10
import type { BoundedDiff } from './generics' ;
11
+ import { typesEquivalent } from './generics' ;
7
12
8
13
// A copy of the same-named type in
9
14
// node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.js, for
@@ -21,3 +26,39 @@ export type ViewStylePropWithout<T: { ... }> = GenericStyleProp<
21
26
// copying that.
22
27
$ReadOnly < $Shape < BoundedDiff < ____ViewStyle_Internal , T >>> ,
23
28
> ;
29
+
30
+ /**
31
+ * A hook for AppState's current state value, updated on 'change' events.
32
+ *
33
+ * Gives `null` if the state isn't one of the documented values
34
+ * (AppStateValues), which the upstream types allow for the initial value,
35
+ * and logs to Sentry in that unexpected case.
36
+ */
37
+ export function useAppState ( ) : null | AppStateValues {
38
+ // Upstream has `?string`… probably they mean `AppStateValues`, but we'll
39
+ // take them at their word and handle the differences by logging, to
40
+ // prompt investigation if needed:
41
+ // - nullish
42
+ // - some string that's not an AppStateValues
43
+ let initialState = AppState . currentState ;
44
+
45
+ if (
46
+ initialState == null
47
+ || ( typeof initialState === 'string'
48
+ && initialState !== 'inactive'
49
+ && initialState !== 'background'
50
+ && initialState !== 'active' )
51
+ ) {
52
+ // If Flow errors here, adjust cases in the conditional.
53
+ typesEquivalent < AppStateValues , 'inactive' | 'background' | 'active' > ( ) ;
54
+ logging . warn ( `Unexpected AppState.currentState: ${ initialState ?. toString ( ) ?? '[nullish]' } ` ) ;
55
+ initialState = null ;
56
+ }
57
+
58
+ const [ value , setValue ] = React . useState ( initialState ) ;
59
+ React . useEffect ( ( ) => {
60
+ const sub = AppState . addEventListener ( 'change' , setValue ) ;
61
+ return ( ) => sub . remove ( ) ;
62
+ } , [ ] ) ;
63
+ return value ;
64
+ }
0 commit comments