diff --git a/examples/NavigationPlayground/js/App.js b/examples/NavigationPlayground/js/App.js
index ac4cb796..a55c7e73 100644
--- a/examples/NavigationPlayground/js/App.js
+++ b/examples/NavigationPlayground/js/App.js
@@ -31,6 +31,7 @@ import SimpleStack from './SimpleStack';
import StackWithHeaderPreset from './StackWithHeaderPreset';
import SimpleTabs from './SimpleTabs';
import TabAnimations from './TabAnimations';
+import TabsWithNavigationFocus from './TabsWithNavigationFocus';
const ExampleInfo = {
SimpleStack: {
@@ -99,7 +100,12 @@ const ExampleInfo = {
name: 'Animated Tabs Example',
description: 'Tab transitions have custom animations',
},
+ TabsWithNavigationFocus: {
+ name: 'Tabs using withNavigationFocus HOC',
+ description: 'Tab views will receive isFocused prop from HOC',
+ },
};
+
const ExampleRoutes = {
SimpleStack: SimpleStack,
SimpleTabs: SimpleTabs,
@@ -124,6 +130,7 @@ const ExampleRoutes = {
path: 'settings',
},
TabAnimations: TabAnimations,
+ TabsWithNavigationFocus: TabsWithNavigationFocus,
};
type State = {
diff --git a/examples/NavigationPlayground/js/TabsWithNavigationFocus.js b/examples/NavigationPlayground/js/TabsWithNavigationFocus.js
new file mode 100644
index 00000000..662269b3
--- /dev/null
+++ b/examples/NavigationPlayground/js/TabsWithNavigationFocus.js
@@ -0,0 +1,48 @@
+/**
+ * @flow
+ */
+
+import React from 'react';
+import { SafeAreaView } from 'react-native';
+import { TabNavigator, withNavigationFocus } from 'react-navigation';
+
+import SampleText from './SampleText';
+
+const createTabScreen = name => {
+ const TabScreen = ({ isFocused }) => (
+
+ {'Tab=' + name}
+ {'IsFocused=' + isFocused ? 'true' : 'false'}
+
+ );
+
+ return withNavigationFocus(TabScreen);
+};
+
+const TabsWithNavigationFocus = TabNavigator(
+ {
+ One: {
+ screen: createTabScreen('One'),
+ },
+ Two: {
+ screen: createTabScreen('Two'),
+ },
+ Three: {
+ screen: createTabScreen('Three'),
+ },
+ },
+ {
+ tabBarPosition: 'bottom',
+ animationEnabled: true,
+ swipeEnabled: true,
+ }
+);
+
+export default TabsWithNavigationFocus;
diff --git a/flow/react-navigation.js b/flow/react-navigation.js
index 8b81a16b..7a43facf 100644
--- a/flow/react-navigation.js
+++ b/flow/react-navigation.js
@@ -1103,4 +1103,7 @@ declare module 'react-navigation' {
declare export function withNavigation(
Component: React$ComponentType
): React$ComponentType;
+ declare export function withNavigationFocus(
+ Component: React$ComponentType
+ ): React$ComponentType;
}
diff --git a/src/react-navigation.js b/src/react-navigation.js
index 1e9e00ba..c2c3e1b0 100644
--- a/src/react-navigation.js
+++ b/src/react-navigation.js
@@ -88,4 +88,7 @@ module.exports = {
get withNavigation() {
return require('./views/withNavigation').default;
},
+ get withNavigationFocus() {
+ return require('./views/withNavigationFocus').default;
+ },
};
diff --git a/src/react-navigation.web.js b/src/react-navigation.web.js
index 2516b832..ad071511 100644
--- a/src/react-navigation.web.js
+++ b/src/react-navigation.web.js
@@ -32,4 +32,7 @@ module.exports = {
get withNavigation() {
return require('./views/withNavigation').default;
},
+ get withNavigationFocus() {
+ return require('./views/withNavigationFocus').default;
+ },
};
diff --git a/src/views/withNavigationFocus.js b/src/views/withNavigationFocus.js
new file mode 100644
index 00000000..59217627
--- /dev/null
+++ b/src/views/withNavigationFocus.js
@@ -0,0 +1,56 @@
+import React from 'react';
+import propTypes from 'prop-types';
+import hoistStatics from 'hoist-non-react-statics';
+import invariant from '../utils/invariant';
+
+export default function withNavigationFocus(Component) {
+ class ComponentWithNavigationFocus extends React.Component {
+ static displayName = `withNavigationFocus(${Component.displayName ||
+ Component.name})`;
+
+ static contextTypes = {
+ navigation: propTypes.object.isRequired,
+ };
+
+ state = {
+ isFocused: false,
+ };
+
+ componentDidMount() {
+ const navigation = this.getNavigation();
+ this.subscriptions = [
+ navigation.addListener('didFocus', () =>
+ this.setState({ isFocused: true })
+ ),
+ navigation.addListener('willBlur', () =>
+ this.setState({ isFocused: false })
+ ),
+ ];
+ }
+
+ componentWillUnmount() {
+ this.subscriptions.forEach(sub => sub.remove());
+ }
+
+ getNavigation = () => {
+ const navigation = this.props.navigation || this.context.navigation;
+ invariant(
+ !!navigation,
+ 'withNavigationFocus can only be used on a view hierarchy of a navigator. The wrapped component is unable to get access to navigation from props or context.'
+ );
+ return navigation;
+ };
+
+ render() {
+ return (
+
+ );
+ }
+ }
+
+ return hoistStatics(ComponentWithNavigationFocus, Component);
+}