Add withNavigation HOC (#137)

This commit is contained in:
Jakub Stasiak
2017-02-06 14:28:04 +01:00
committed by Satyajit Sahoo
parent d2fc150f69
commit aead8ff9fb
9 changed files with 102 additions and 2 deletions

View File

@@ -0,0 +1,17 @@
# withNavigation
[`withNavigation`](/src/views/withNavigation.js) is a Higher Order Component which passes the `navigation` prop into wrapped Component. It's useful when you cannnot pass the `navigation` prop into into the component directly, or don't want to pass it in case of a deeply nested child.
## Example
```js
import { Button } 'react-native';
import { withNavigation } from 'react-navigation';
const MyComponent = ({ to, navigation }) => (
<Button title={`navigate to ${to}`} onPress={() => navigation.navigate(to)} />
);
const MyComponentWithNavigation = withNavigation(MyComponent);
```

View File

@@ -19,6 +19,7 @@ import ModalStack from './ModalStack';
import StacksInTabs from './StacksInTabs';
import SimpleStack from './SimpleStack';
import SimpleTabs from './SimpleTabs';
import WithNavigation from './WithNavigation';
const ExampleRoutes = {
SimpleStack: {
@@ -63,6 +64,11 @@ const ExampleRoutes = {
screen: SimpleTabs,
path: 'settings',
},
WithNavigation: {
name: 'withNavigation HOC',
description: 'Navigating using `withNavigation` HOC',
screen: WithNavigation,
},
};
const MainScreen = ({ navigation }) => (

View File

@@ -0,0 +1,33 @@
/* @flow */
import React from 'react';
import {
View,
Text,
Button,
} from 'react-native';
import { TabNavigator, withNavigation } from 'react-navigation';
const ButtonWithNavigation = withNavigation(({ navigation, to, ...rest }) => (
<Button {...rest} onPress={() => navigation.navigate(to)} />
));
const createTabWithNavigationButtons = (tabName: string, links: Array<string>) => {
const Tab = () => (
<View>
<Text>This is tab: {tabName}</Text>
<Text>You can navigate to:</Text>
{links.map(link => (
<ButtonWithNavigation key={link} to={link} title={link} />
))}
</View>
);
return Tab;
};
export default TabNavigator({
Tab1: { screen: createTabWithNavigationButtons('Tab1', ['Tab2', 'Tab3']) },
Tab2: { screen: createTabWithNavigationButtons('Tab2', ['Tab3', 'Tab1']) },
Tab3: { screen: createTabWithNavigationButtons('Tab2', ['Tab2', 'Tab1']) },
});

View File

@@ -65,6 +65,7 @@
"dependencies": {
"clamp": "^1.0.1",
"fbjs": "^0.8.5",
"hoist-non-react-statics": "^1.2.0",
"path-to-regexp": "^1.7.0",
"react-native-drawer-layout": "^1.1.0",
"react-native-tab-view": "^0.0.54"

View File

@@ -441,3 +441,7 @@ export type NavigationSceneRenderer = (
export type NavigationStyleInterpolator = (
props: NavigationSceneRendererProps,
) => Object;
export type ContextWithNavigation = {
navigation: NavigationScreenProp<NavigationState, NavigationAction>;
};

View File

@@ -26,4 +26,7 @@ module.exports = {
get CardStack() { return require('./views/CardStack').default; },
get DrawerView() { return require('./views/Drawer/DrawerView').default; },
get TabView() { return require('./views/TabView/TabView').default; },
// HOCs
get withNavigation() { return require('./views/withNavigation').default; },
};

View File

@@ -6,6 +6,7 @@ import type {
NavigationScreenProp,
NavigationState,
NavigationAction,
ContextWithNavigation,
} from '../TypeDefinition';
type Props = {
@@ -15,8 +16,19 @@ type Props = {
};
export default class SceneView extends PureComponent<void, Props, void> {
static childContextTypes = {
navigation: React.PropTypes.object.isRequired,
};
props: Props;
getChildContext(): ContextWithNavigation {
return {
navigation: this.props.navigation,
};
}
render() {
const { screenProps, navigation, component: Component } = this.props;
return <Component {...screenProps} navigation={navigation} />;

View File

@@ -0,0 +1,20 @@
/* @flow */
import React from 'react';
import hoistStatics from 'hoist-non-react-statics';
import { ContextWithNavigation } from '../TypeDefinition';
export default function withNavigation(Component: ReactClass<T>) {
const componentWithNavigation = (props: T, { navigation }: ContextWithNavigation) => (
<Component {...props} navigation={navigation} />
);
componentWithNavigation.displayName = `withNavigation(${Component.displayName || Component.name})`;
componentWithNavigation.contextTypes = {
navigation: React.PropTypes.object.isRequired,
};
return hoistStatics(componentWithNavigation, Component);
}

View File

@@ -2415,6 +2415,10 @@ hoek@2.x.x:
version "2.16.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
hoist-non-react-statics@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
home-or-tmp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
@@ -3361,13 +3365,13 @@ mime-db@~1.23.0:
version "1.23.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.23.0.tgz#a31b4070adaea27d732ea333740a64d0ec9a6659"
mime-types@2.1.11, mime-types@~2.1.7:
mime-types@2.1.11, mime-types@~2.1.7, mime-types@~2.1.9:
version "2.1.11"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.11.tgz#c259c471bda808a85d6cd193b430a5fae4473b3c"
dependencies:
mime-db "~1.23.0"
mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.13, mime-types@~2.1.6, mime-types@~2.1.9:
mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.13, mime-types@~2.1.6:
version "2.1.14"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.14.tgz#f7ef7d97583fcaf3b7d282b6f8b5679dab1e94ee"
dependencies: