React Native applications often use two or more navigators at once. At first, I had a problem with the combination of stack navigator and drawer navigator, fortunately I combined them in way, that they work properly and now I can share this knowledge.
If you don’t know how to use navigation in React Native, check out my previous entries: StackNavigator example and DrawerNavigator example
Let’s start from the beginning, which is App.js component. In our case, it will be very simple, because it returns only one component, which is DrawerNavigator.
App.js
import React, {Component} from 'react';
import DrawerNavigator from './components/DrawerNavigator';
export default class App extends Component {
render() {
return (
<DrawerNavigator />
);
}
}
In the drawer navigator we create four screens – one main, which contains StackNavigator and three others, which contains other data.
DrawerNavigator.js
import React, {Component} from 'react';
import { createDrawerNavigator, createAppContainer } from 'react-navigation';
import Screen1 from './Screen1';
import Screen2 from './Screen2';
import Screen3 from './Screen3';
import ContentComponent from './ContentComponent';
import {Dimensions} from 'react-native';
import StackNavigator from './StackNavigator';
const MyDrawerNavigator = createDrawerNavigator({
Home: {screen: StackNavigator},
Screen1: {screen: Screen1},
Screen2: {screen: Screen2},
Screen3: {screen: Screen3},
},
{
initialRouteName: 'Home',
drawerWidth: Dimensions.get('window').width,
drawerPosition: 'left',
}
);
const AppContainer = createAppContainer(MyDrawerNavigator);
export default class DrawerNavigator extends Component {
render() {
return <AppContainer />;
}
}
As you can see as the main screen (initialRouteName) in the drawer navigator we set StackNavigator, so let’s deal with this component
StackNavigator.js
import React, {Component} from 'react';
import { createStackNavigator, createAppContainer, DrawerActions } from 'react-navigation';
import HomeScreen from './HomeScreen';
import Screen4 from './Screen4';
import Screen5 from './Screen5';
const MyStackNavigator = createStackNavigator(
{
Home: {screen: HomeScreen},
Screen4: Screen4,
Screen5: Screen5,
},
{
initialRouteName: 'Home',
defaultNavigationOptions: {
headerStyle: { height: 55, backgroundColor: 'orange' },
//headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold', color: '#fff' },
},
transitionConfig: () => ({
transitionSpec: {
duration: 500,
},
screenInterpolator: sceneProps => {
const { position, layout, scene } = sceneProps;
const index = scene.index;
const width = layout.initWidth;
const slideFromRight = {
opacity: position.interpolate({
inputRange: [ index, index + 1],
outputRange: [1, 1],
}),
transform: [{
translateX: position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [width, 0, -20],
})
}] };
return slideFromRight;
},
}),
}
);
const AppContainer = createAppContainer(MyStackNavigator);
export default class StackNavigator extends Component {
render() {
return <AppContainer screenProps={{ openDraw: () => this.props.navigation.dispatch(DrawerActions.openDrawer()) }} />;
}
}
Here case is a bit different: as the main screen we set HomeScreen and from its level (specifically from the header) we want to open the drawer navigator. However, the navigation property in the stack navigator does not have the option to open drawer navigator. That’s why we need to pass this option from drawer navigator to stack navigator, and from it to the HomeScreen main component. We will do this by passing it with screenProps – as an additional property.
Now in the HomeScreen component we can read the property opening the drawer navigator and place it in the header using static navigationOptions.
HomeScreen.js
import React, {Component} from 'react';
import {StyleSheet, Text, View, TouchableHighlight, Button} from 'react-native';
export default class HomeScreen extends Component {
static navigationOptions = ({ screenProps }) => ({
title: 'Home',
headerLeft: (
<Button onPress={() => screenProps.openDraw() }
title="OPEN"
color="red"
/>
),
})
render() {
return (
<View style={styles.view}>
<Text style={styles.text}>This is homescreen</Text>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Screen4')} style={styles.touchableHighlight} underlayColor={'#f1f1f1'}>
<Text style={styles.text}>Go to Screen 2</Text>
</TouchableHighlight>
</View>
);
}
}
You can add styles by yourself 😉
Effect is here: