forked from peter-mach/react-navigation-is-focused-hoc
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
88 lines (75 loc) · 2.59 KB
/
index.js
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
import React from 'react';
import PropTypes from 'prop-types';
// subscribed components update functions
const subscribedComponents = [];
function getCurrentRouteKey(navigationState) {
if (!navigationState) return null;
const route = navigationState.routes[navigationState.index];
if (route.routes) return getCurrentRouteKey(route);
return route.key;
}
function updateFocus(currentState) {
const currentRouteKey = getCurrentRouteKey(currentState);
subscribedComponents.forEach(f => f(currentRouteKey));
}
function withNavigationFocus(WrappedComponent) {
class WithNavigationFocus extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired,
};
static navigationOptions = props => {
if (typeof WrappedComponent.navigationOptions === 'function') {
return WrappedComponent.navigationOptions(props);
}
return { ...WrappedComponent.navigationOptions };
};
constructor(props) {
super(props);
this.state = {
isFocused: true,
focusedRouteKey: props.navigation.state.key,
};
this.isFocused = true;
}
componentDidMount() {
subscribedComponents.push(this._handleNavigationChange);
}
componentWillUnmount() {
for (var i = 0; i < subscribedComponents.length; i++) {
if (subscribedComponents[i] === this._handleNavigationChange) {
subscribedComponents.splice(i, 1);
break;
}
}
}
_handleNavigationChange = routeKey => {
// update state only when isFocused changes
const currentScreenKey = this.props.navigation.state.key;
// when handling a navigation action that has nested actions, this method
// will be called twice or more. in this case, a later call may not see a
// change to this.state.isFocused even if this.setState already ran, since
// React batches updates. so we need to check a local variable that
// immediately reflects any changes.
if (this.isFocused !== (currentScreenKey === routeKey)) {
this.setState({
isFocused: !this.isFocused,
focusedRouteKey: routeKey,
});
this.isFocused = !this.isFocused;
}
};
render() {
return (
<WrappedComponent
isFocused={this.state.isFocused}
focusedRouteKey={this.state.focusedRouteKey}
{...this.props}
/>
);
}
}
WithNavigationFocus.displayName =
WrappedComponent.displayName || WrappedComponent.name || 'Component';
return WithNavigationFocus;
}
export { getCurrentRouteKey, withNavigationFocus, updateFocus };