Reputation: 513
I am developing an app using react-native-navigation and I want to have a StackNavigator and a DrawerNavigator in the project. So, I have implemented them in the app.js but the apps crashes giving this error "The development server returned response error with code: 500".I have implemented them separetly and it works but I couldn't implement them together.Any suggestion?
this is my code for app.js
import React, {
Component
} from 'react';
import {
StyleSheet,
Text,
View
} from 'react-native';
import {
createStackNavigator,
DrawerNavigator,
DrawerItems
} from "react-navigation";
import {
Container,
Header,
Content,
Thumbnail,
Button,
Body
} from 'native-base';
import Profile from './components/Profile.js';
import Main from './components/Main.js';
import Login from './components/Login.js';
import Product from './components/Product.js';
export default class App extends Component {
render() {
return (
<Navapp />
);
}
}
const styles = StyleSheet.create({
// styles here
});
export const Drawer = DrawerNavigator({
Main: {
screen: Main
},
Profile: {
screen: Profile
},
}, {
initialRouteName: 'Main',
contentComponent: CustomDrawer,
drawerPosition: 'Left',
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle',
});
export const CustomDrawer = (props) => (
<Container>
<Header style = {
styles.headerStyle
}>
<Body style = {
styles.bodyStyle
}>
<Thumbnail style = {
{
height: 100,
width: 100
}
}
source = {
require('../image/logo.png')
}/>
</Body>
</Header>
<Content>
<DrawerItems { ...props} />
</Content >
</Container>
)
export const Navapp = createStackNavigator({
Login: {
screen: Login
},
Drawer: {
screen: Drawer
},
Product: {
screen: Product
},
});
Upvotes: 9
Views: 14034
Reputation: 567
Probably the way we can implement both Stack and Drawer Navigation has been made much simpler. Here you guys can refer to my code.
import * as React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import { createDrawerNavigator } from "@react-navigation/drawer";
import MenuComponent from "../MenuComponent";
import DishDetailComponent from "../DishDetailComponent";
import HomeComponent from "../HomeComponent";
/**
* @author BadalSherpa
* @function HomeNavigation
**/
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const HomeNavigation = (props) => {
return (
<Stack.Navigator initialRouteName='Home'>
<Stack.Screen name='Home' component={HomeComponent} />
<Stack.Screen name='Menu' component={MenuComponent} />
<Stack.Screen name='Dish-Detail' component={DishDetailComponent} />
</Stack.Navigator>
);
};
const MenuNavigation = (props) => {
return (
<Stack.Navigator initialRouteName='Home'>
<Stack.Screen name='Menu' component={MenuComponent} />
</Stack.Navigator>
);
};
const DrawerNavigation = () => {
return (
<Drawer.Navigator>
<Drawer.Screen name='Home' component={HomeNavigation} /> //Here is where we are combining Stack Navigator to Drawer Navigator
<Drawer.Screen name='Menu' component={MenuNavigation} />
</Drawer.Navigator>
);
};
export default DrawerNavigation;
Then you can simple return this inside NavigationContainer which will have both Stack and Drawer Navigator working together.
<NavigationContainer>
<HomeNavigation />
</NavigationContainer>
Upvotes: 2
Reputation: 2206
This is a slightly different take where the drawer navigator controls a stack navigator. Each selection in the drawer will push a child stack element so there is a one-to-one match between the drawer and stack. This is more typical behavior in my experience. All but the home have a title with back navigation indicator.
import React from 'react';
import {SafeAreaView, StyleSheet} from 'react-native';
import {
CompositeNavigationProp,
NavigationContainer,
} from '@react-navigation/native';
import {
createStackNavigator,
StackNavigationProp,
} from '@react-navigation/stack';
import HomeScreen from './HomeScreen';
import SettingsScreen from './SettingsScreen';
import {
createDrawerNavigator,
DrawerContentComponentProps,
DrawerContentOptions,
DrawerContentScrollView,
DrawerItem,
DrawerNavigationProp,
} from '@react-navigation/drawer';
type NoProps = Record<string, object>;
export type ScreenNavigationProps = CompositeNavigationProp<
StackNavigationProp<NoProps>,
DrawerNavigationProp<NoProps>
>;
export type DrawerProps = DrawerContentComponentProps<DrawerContentOptions>;
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator(); // https://reactnavigation.org/docs/stack-navigator/
/**
* Render the content of the drawer. When an item is selected
* it closes the drawer and pushes an element on the stack nav.
* @param props
*/
function CustomDrawerContent(props: DrawerProps) {
const navigation = (props.navigation as unknown) as ScreenNavigationProps;
const openScreen = (name: string) => () => {
navigation.navigate('Home', {screen: name});
navigation.closeDrawer();
};
return (
<DrawerContentScrollView {...props}>
{/* <DrawerItemList {...props} /> */}
<DrawerItem label="Home" onPress={openScreen('Home')} />
<DrawerItem label="Settings" onPress={openScreen('Settings')} />
</DrawerContentScrollView>
);
}
/**
* Render the Home Stack Navigator.
*/
function HomeStack() {
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={HomeScreen}
options={{headerShown: false}}
/>
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
);
}
/**
* Render the Home Drawer with a custom drawerContent.
*/
function HomeDrawer() {
return (
<Drawer.Navigator
initialRouteName="Home"
drawerContent={(props) => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="Home" component={HomeStack} />
</Drawer.Navigator>
);
}
const App = () => {
return (
<SafeAreaView style={styles.app}>
<NavigationContainer>
<HomeDrawer />
</NavigationContainer>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
app: {flex: 1},
});
export default App;
The HomeScreen can provide a menu to open the drawer:
const navigation = useNavigation<ScreenNavigationProps>();
const openDrawer = () => {
navigation.openDrawer();
};
Upvotes: 0
Reputation: 57
same issue with me, Then i just change my emulator and update the version and it worked 100%.
Upvotes: 0
Reputation: 191
I had a very similar setup for my app, this is how I went about handling it. First I created a stack navigator with the routes that I wanted logged in users to see, and I place that navigator inside a drawer navigator (you can put more than one in there if you want). Finally I created my top-level navigator, whose initial route points to the login page; upon logging in I navigate the user to the second route, which points to my drawer navigator.
In practice it looks like this:
// Main Screens for Drawer Navigator
export const MainStack = StackNavigator({
Dashboard: {
screen: Dashboard,
navigationOptions: {
title: 'Dashboard',
gesturesEnabled: false,
headerLeft: null
}
},
Notifications: {
screen: Notifications,
navigationOptions: {
title: 'Notifications'
}
}
}, { headerMode: 'screen' } );
// Drawer Navigator
export const Drawer = DrawerNavigator({
MainStack: {
screen: MainStack
}
});
// Main App Navigation
export const AppStack = StackNavigator({
Login: {
screen: Login,
navigationOptions: {
header: null,
gesturesEnabled: false
}
},
Drawer: {
screen: Drawer,
navigationOptions: {
header: null,
gesturesEnabled: false
}
}
}, { headerMode: 'none' } );
// In Your App.js
<AppStack />
Note that in the last stack navigator, the drawer screen has header set to null; this is because with nested stack navigators you can sometimes run into an issue where you'll have duplicate headers. This will hide the top-level navigator's header and let you show / customize the headers for your nested navigators.
Upvotes: 7
Reputation: 10317
This is how I use them
const HomeStackNavigator = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Chat: {
screen: ChatScreen,
},
},
{
initialRouteName: 'Home',
headerMode: 'screen',
},
);
const MainDrawerNavigator = DrawerNavigator(
{
Home: {
screen: HomeStackNavigator,
},
},
{
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle',
contentComponent: SlideMenu,
navigationOptions: {
drawerLockMode: 'locked-closed',
},
},
);
Upvotes: 1