Drawer navigator in react-native using react-navigation 4.x - react-native

I want to create a drawer navigator using react navigation 4.x in react native, but not getting drawer menu in left side of the screen. Here is my code for the navigation component.
It includes three screens First,Home and Login that i want to show in drawer menu.
import {
createSwitchNavigator,
createAppContainer,
//createDrawerNavigator,
// createBottomTabNavigator,
} from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { createDrawerNavigator } from 'react-navigation-drawer';
import FirstScreen from '../screen/FirstScreen';
import HomeScreen from '../screen/HomeScreen';
import LoginScreen from '../screen/LoginScreen';
const AppStack = createStackNavigator ({
First: {screen: FirstScreen},
// Dashboard: {screen: AppDrawerNavigator},
Login: {screen: LoginScreen},
Home: {screen: HomeScreen},
})
const AppDrawerNavigator = createDrawerNavigator({
Dashboard: {screen:AppStack}
});
const switchNavigator = createSwitchNavigator({
First: {screen: FirstScreen},
Dashboard: {screen: AppDrawerNavigator},
Login: {screen: LoginScreen},
Home: {screen: HomeScreen},
});
const AppNavigator = createAppContainer(switchNavigator);
export default AppNavigator;

If you want to keep your AppStack as stackNavigator then you have to create custom drawer navigator and need to pass it on createDrawerNavigator.
So first create CustomDrawer.js as below :
import React, { Component } from 'react';
import { View, Text, ScrollView, TouchableOpacity } from 'react-native';
import { NavigationActions } from 'react-navigation';
class CustomDrawer extends Component {
constructor(props) {
super(props);
this.state = {
menus: [
key: 'First', title: 'First', screen: 'FirstScreen',
key: 'Login', title: 'Login', screen: 'LoginScreen',
key: 'Home', title: 'Home', screen: 'HomeScreen'
]
};
}
navigateToScreen = (route) => {
const navigateAction = NavigationActions.navigate({
routeName: route
});
this.props.navigation.dispatch(navigateAction);
this.props.navigation.closeDrawer();
}
render() {
return (
<ScrollView style={{flex: 1}}>
{
this.state.menus.map((menu) => (
<TouchableOpacity key={menu.key} onPress={() => this.navigateToScreen(menu.screen)}>
<Text>{menu.title}</Text>
</TouchableOpacity>
))
}
</ScrollView>
);
}
}
export default CustomDrawer;
Then on in your AppNavigator.js pass CustomDrawer as contentComponent in createDrawerNavigator as below :
const DrawerNavigator = createDrawerNavigator({
Dashboard: {
screen: AppStack,
}
}, {
contentComponent: CustomDrawer, // Pass here
// others props
drawerBackgroundColor: 'rgba(255,255,255,.9)',
overlayColor: 'rgba(0,0,0,0.5)',
contentOptions: {
activeTintColor: '#fff',
activeBackgroundColor: '#6b52ae',
},
});
If you want more style you can done in CustomDrawer.js.

you are returning the switch navigator, try this way , embed switch-navigator object with drawer-navigator object and return drawer-navigator object. refer below,
const AppDrawerNavigator = createDrawerNavigator({
First: {screen: FirstScreen},
Login: {screen: LoginScreen},
Home: {screen: HomeScreen},
switchNavigator: switchNavigator
});
const AppNavigator = createAppContainer(AppDrawerNavigator);
export default AppNavigator;

Related

error adding a splash to my expo react native app

I have my next splash, my idea is to be able to show my app logo when opening the application and then go to the start of the application, it works fine:
import React from 'react';
import { StyleSheet, Image, View, Text } from 'react-native';
import { StackActions, NavigationActions } from 'react-navigation';
export default class Splash extends React.Component {
goToScreen(routeName){
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: routeName })],
});
this.props.navigation.dispatch(resetAction);
}
/*goToScreen(routeName){
this.props.navigation.navigate(routeName)
}*/
componentDidMount(){
setTimeout( () => {
this.goToScreen('Home')
}, 2000, this)
}
render(){
return (
<View style={styles.container}>
<Image source={{uri: 'https://i.imgur.com/r0jUwOD.png'}} style={{width: 250, height: 250}} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#33B747',
alignItems: 'center',
justifyContent: 'center'
},
});
The problem is the location of the splash, since in this way if it shows me, but it creates a lower button called Splash, on the other hand the splash when loading is shown in conjunction with the lower buttons and that should not happen, the splash must display only in full screen and not create a button.
AppNavigator.js
import React from 'react';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createAppContainer } from 'react-navigation';
import { MaterialIcons, MaterialCommunityIcons } from '#expo/vector-icons';
import Splash from '../screens/Splash';
import NewsListScreen from '../screens/NewsListScreen';
import NewsItemScreen from '../screens/NewsItemScreen';
const StackNavigator = createStackNavigator({
Splash: {
screen: Splash,
navigationOptions: {
headerShown: false,
}
},
News: {
screen: NewsListScreen
},
Root: {
screen: BottomTabNavigator,
},
NewsItem: {
screen: NewsItemScreen,
navigationOptions: {
headerTitle: 'News Item'
}
},
},{
initialRouteName: 'Splash'
});
const BottomTabNavigator = createBottomTabNavigator({
Home: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialIcons name="home" size={24} />
}
},
News: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialCommunityIcons name="newspaper-variant-outline" size={24} />
}
}
})
export default createAppContainer(BottomTabNavigator);
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { AppLoading } from 'expo';
import { Provider } from 'react-redux';
import AppNavigator from './app/resources/navigation/AppNavigator';
import ReduxStore from './app/resources/redux/ReduxStore';
export default function App() {
return (
<Provider store={ReduxStore}>
<AppNavigator />
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Attached capture of the error upload in imgur capture 1 and capture 2
The recommended way to add a splash screen to an expo managed app can be found here.
I've managed to create an expo project and achieve the exact same behavior that you've looking for.
I've used react-navigation 4.x.x
This is how it looks and you can find the full code here
Here is the code I've used.
Splash.js
import React, { Component } from "react";
import { Text, SafeAreaView, View, StyleSheet } from "react-native";
import { StackActions, NavigationActions } from "react-navigation";
export class Splash extends Component {
goToScreen(routeName) {
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: routeName })],
});
this.props.navigation.dispatch(resetAction);
}
componentDidMount() {
setTimeout(
() => {
this.goToScreen("Root");
},
2000,
this
);
}
render() {
return (
<SafeAreaView style={styles.mainContainer}>
<Text style={styles.text}> Splash Screen </Text>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#efef21",
},
text: {
fontSize: 22,
},
});
export default Splash;
Navigator.js
import { createStackNavigator } from "react-navigation-stack";
import { createAppContainer } from "react-navigation";
import Home from "./Home";
import Splash from "./Splash";
import TabNavigator from "./BottomTabNavigator";
const AppNavigator = createStackNavigator(
{
Splash: {
screen: Splash,
navigationOptions: {
headerShown: false,
},
},
Root: {
screen: TabNavigator,
navigationOptions: {
headerShown: false,
},
},
},
{
initialRouteName: "Splash",
}
);
export default createAppContainer(AppNavigator);
BottomTabNavigator.js
import { createAppContainer } from "react-navigation";
import { createBottomTabNavigator } from "react-navigation-tabs";
import Home from "./Home";
import News from "./News";
const TabNavigator = createBottomTabNavigator({
Home: {
screen: Home,
navigationOptions: {
title: "Home",
},
},
News: {
screen: News,
navigationOptions: {
title: "News",
},
},
});
export default createAppContainer(TabNavigator);
Also, I've achieved the same behavior using react-navigation 5.x.x
You can find my code here
Edit 01
If you want to have the headers, You need to use a Stack Navigator for each tab.
Here is the updated code of BottomTabNAvigator.js
import { createAppContainer } from "react-navigation";
import { createBottomTabNavigator } from "react-navigation-tabs";
import { createStackNavigator } from "react-navigation-stack";
import Home from "./Home";
import News from "./News";
const HomeStack = createStackNavigator({
Home: Home,
});
const NewsStack = createStackNavigator({
News: News,
});
const TabNavigator = createBottomTabNavigator({
Home: {
screen: HomeStack,
navigationOptions: {
headerTitle: "Home",
title: "Home",
},
},
News: {
screen: NewsStack,
navigationOptions: {
title: "News",
},
},
});
export default createAppContainer(TabNavigator);
You have used Splash: {screen: Splash}, in your BottomTabNavigator so obviously it will add splash as on bottom navigator.
Remove Splash: {screen: Splash}, from BottomTabNavigator and paste it on StackNavigator and set splash as initialRouteName
const StackNavigator = createStackNavigator({
News: {
screen: NewsListScreen
},
Splash: {screen: Splash},
NewsItem: {
screen: NewsItemScreen,
navigationOptions: {
headerTitle: 'News Item'
}
},
},
{
initialRouteName : 'Splash'
});
you have to move splash screen to StackNavigator and add BottomTabNavigator into StackNavigator as a screen like this
import React from 'react';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createAppContainer } from 'react-navigation';
import { MaterialIcons } from '#expo/vector-icons';
import Splash from '../screens/Splash';
import NewsListScreen from '../screens/NewsListScreen';
import NewsItemScreen from '../screens/NewsItemScreen';
const StackNavigator = createStackNavigator({
Splash: {
screen: Splash
},
Home: {
screen: BottomTabNavigator
},
News: {
screen: NewsListScreen
},
NewsItem: {
screen: NewsItemScreen,
navigationOptions: {
headerTitle: 'News Item'
}
}
},
{
initialRouteName: "Splash",
});
const BottomTabNavigator = createBottomTabNavigator({
Home: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialIcons name="home" size={24} />
}
}
})
export default createAppContainer(StackNavigator);

How to make screen or component on top of other screens

I'm making a music app and what I want to do is to implement a music player screen that can be active on all other screens something like this:
https://reactnativeexample.com/react-native-swipe-up-down-component/
This is my app.js:
import React, {Component} from 'react';
import { createDrawerNavigator, createStackNavigator, createAppContainer } from "react-navigation";
import HomeScreen from './screens/home';
import SideBar from './screens/sidebar';
import SongScreen from './screens/song';
const Drawer = createDrawerNavigator(
{
Home: {screen: HomeScreen}
},
{
initialRouteName: "Home",
contentOptions: {
activeTintColor: "#e91e63"
},
contentComponent: props => <SideBar {...props} />
}
);
const AppNavigator = createStackNavigator(
{
Drawer: { screen: Drawer },
SongScreen: { screen: SongScreen }
},
{
initialRouteName: "Drawer",
headerMode: "none"
}
);
const AppContainer = createAppContainer(AppNavigator);
export default class App extends Component {
render() {
return (
<AppContainer />
);
}
}
use https://github.com/octopitus/rn-sliding-up-panel and make your root screen look like this:
<View>
<AppContainer/>
<SlidingUpPanel/>
</View

React-Navigation adding drawer navigation with tab

I'm using react-navigation ("^3.0.9") with expo.
This is my logic flow:
TabView(BottomTabNavigator) with StackNavigatior:
HomeStack
--HomeScreen
...
LinksStack
--LinkScreen
...
SettingsStack
-- Aboutscreen
...
Everything works ok, but now I would like to add a drawer navigation (hamburger menu) as follows:
DrawerNavigation View
--HomeScreen(which will show HomeScreen with 3 tabs)
--Screen2 (no tabs)
--Screen3 (no tabs)
Which I tried to do the following:
export const Tab = createBottomTabNavigator({
HomeStack,
LinksStack,
SettingsStack,
}
);
export const Drawer = DrawerNavigator({
HomeScreen: { screen: HomeScreen },
Screen2: { screen: Screen2 },
Screen3: { screen: Screen3 },
});
which they returned an error of undefined is not a function
the original code was to export the default bottom tab navigator only like,
//export default createBottomTabNavigator({
// HomeStack,
// LinksStack,
// SettingsStack,
// }
// );
How do I implement both BottomTabNavigator and DrawerNavigator together?
--Code as below
My App.js which calls AppNavigator
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator />
</View>
);
}
}
which AppNavigator calls MainTabNavigator
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import MainTabNavigator from './MainTabNavigator';
export default createAppContainer(createSwitchNavigator({
Main: MainTabNavigator,
}
));
an example of my stackNavigator with Tab
const HomeStack = createStackNavigator({
Home: HomeScreen,
HomeDetail: HomeDetailScreen
});
HomeStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-home`
: 'md-home'
}
/>
),
};
Update:
I have done a correct working snack example in which anyone can reference from.
You need to add the tabNavigator inside the DrawerNavigator.
const ProfileNavigator = createDrawerNavigator({
Drawer: DashboardTabNav
}, {
initialRouteName: 'Drawer',
contentComponent: ExampleScreen,
drawerWidth: 300
});
// Manifest of possible screens
const PrimaryNav = createStackNavigator({
DashboardScreen: { screen: ProfileNavigator },
LoginScreen: { screen: LoginScreen },
LaunchScreen: { screen: LaunchScreen },
UpdateUserScreen: { screen: UpdateUserScreen }
}, {
// Default config for all screens
headerMode: 'none',
initialRouteName: 'LoginScreen',
navigationOptions: {
headerStyle: styles.header
}
});
export default createAppContainer(PrimaryNav);
Take a look at how to open drawer without navigating to the screen from one of the tabs of tabnavigator?
or
https://readybytes.in/blog/how-to-integrate-tabs-navigation-drawer-navigation-and-stack-navigation-together-in-react-navigation-v2
Also for full example take a look at https://gitlab.com/readybytes/ReactNavigationExampleVersion2

React Navigation - navigating between screens

I'm trying to navigate between screens in React Native, by using React Navigation.
Currently, I have the following. Note that EmployeeStack is nested inside of RootStack.
RootStack.js:
import LoginForm from '../components/LoginForm';
import EmployeeStack from './EmployeeStack';
import { StackNavigator } from 'react-navigation';
const routes = {
Home: {screen: LoginForm},
EmployeeList: {screen: EmployeeStack}
};
const options = {
initialRouteName: 'Home'
};
const RootStack = StackNavigator(routes, options);
export default RootStack;
EmployeeStack.js:
import EmployeeList from '../components/EmployeeList';
import AnotherScreen from '../components/AnotherScreen';
import { StackNavigator } from 'react-navigation';
const routes = {
EmployeeList: {screen: EmployeeList},
AnotherScreen: {screen: AnotherScreen},
};
const options = {
initialRouteName: 'EmployeeList'
};
const EmployeeStack = StackNavigator(routes, options);
export default EmployeeStack;
In EmployeeList.js, I have a button that does this:
<Button
onPress={() => this.props.navigation.navigate('AnotherScreen')}
title="Go123"
color="#841584"
/>
This button does not navigate to AnotherScreen when pressed. Interestingly though, if I change the navigate argument to 'EmployeeList' or 'Home', it navigates to those screens properly.
How can I navigate to AnotherScreen?
In order to navigate between screens from login -> home screen you need to define separate navigation. Use primary navigation as common for other navigations
import HomeScreen from "../screens/user/Home";
import LoginScreen from "../screens/Login";
import ContactScreen from "../screens/Contact";
import LogoutScreen from "../screens/Logout";
........
const LoginStack = StackNavigator({
loginScreen: { screen: LoginScreen },
// signupScreen: { screen: SignupScreen },
// forgottenPasswordScreen: { screen: ForgottenPasswordScreen, navigationOptions: { title: 'Forgot Password' } }
}, {
headerMode: 'none',
navigationOptions: {
headerVisible: false,
gesturesEnabled: false,
}
})
const HomeNavigation = StackNavigator({
HomeStack: { screen: HomeStack }
}, {
headerMode: 'float',
navigationOptions: ({navigation}) => ({
gesturesEnabled: false,
headerStyle: {backgroundColor: '#29B1FC'},
headerTintColor: '#ffffff',
}),
})
const HomeStack = DrawerNavigator({
HomeScreen: { screen: HomeScreen },
ContactScreen: { screen: ContactScreen },
LogoutScreen: { screen: LogoutScreen },
},
{
contentOptions: {
activeTintColor: 'black',
activeBackgroundColor : 'transparent',
inactiveTintColor : 'black',
itemsContainerStyle: {
marginVertical: 0,
},
iconContainerStyle: {
opacity: 1,
},
itemStyle :{
height : 50,
}
},
}
)
const PrimaryNav = StackNavigator({
loginStack: { screen: LoginStack },
HomeStack: { screen: HomeNavigation },
}, {
// Default config for all screens
headerMode: 'none',
title: 'Main',
initialRouteName: 'loginStack'
})
export default PrimaryNav
........
And your button press will work like this
<Button
onPress={() => this.props.navigation.navigate('HomeStack')}
//HomeStack = navigation of PrimaryNav
title="Go123"
color="#841584"
/>

Toggling a drawer from header icon using react-navigation

I am new to react-native and react-navigation.
Required Screen: A home page with a header (Thumbnail + title) , two tabs and a drawer that toggles onPress of the thumbnail.
Please check my code:
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import {Icon, Button} from 'native-base';
const util = require('util');
import { TabNavigator, StackNavigator, DrawerNavigator, NavigationActions } from 'react-navigation';
import FirstScreen from './tabs/FirstScreen';
import SecondScreen from './tabs/SecondScreen';
import Profile from './Profile';
import SearchScreen from './tabs/SearchScreen';
const DrawerScreens = DrawerNavigator({
Profile: {screen: Profile}
},{
drawerPosition: 'left',
drawerWidth: 150
});
// A drawer navigator
const TabScreens= TabNavigator({
First: {screen: FirstScreen},
Second: {screen: SecondScreen}
});
// Started with a tab navigator to register two tabs
const MenuButton =({navigation})=>{
return(
<View>
<TouchableOpacity onPress={()=>(navigation.navigate('DrawerToggle'))}>
<Icon name="person" size= {20}/>
</TouchableOpacity>
</View>)};
export const StackScreens= StackNavigator({
Draw: {screen: DrawerScreens},
// Drawer navigator as a screen
Display: {screen: TabScreens,
// Making the tabnavigator as a screen
navigationOptions: ({navigation})=>({
title: 'Welcome',
headerLeft: <MenuButton navigation={navigation} />
})
},
},{
initialRouteName: 'Display'
});
On pressing of the thumbnail the TabScreens navigates to the DrawerScreens (since that is how i coded). I want to make it toggle. Can someone please help me.
Here's some general ideas on how to structure your navigator properly.
What react-navigation version are you using?
Try changing your MenuButton helper method to this and see if it helps
if (navigation.state.index === 0) {
navigation.navigate('DrawerOpen')
} else {
navigation.navigate('DrawerClose')
}