Is it Possible to navigate from createStackNavigator to createDrawerNavigator? - react-native

How is this implemented
I have a stack navigator which i use for Splashscreen and Login, this works fine , now i have a drawerNavigator which is the main home of the Application, Now my worry is, Is this possible , navigating from a stack navigator (username and password) and landing at a homepage (DrawerNavigator) (home page with left side menu)
My code is looking something like this, its a very long code I know, but pls at the same time, I just started out react-native some few days ago. Does anyone think its advisable to use createStackNavigator as well as createDrawerNavigator at the same time?
import React , {Component} from 'react';
import { Platform, View, Text, Image , StyleSheet , ActivityIndicator, Dimensions, Modal, TextInput, TouchableOpacity, Alert } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createDrawerNavigator } from 'react-navigation-drawer';
import { Header } from 'react-native-elements';
import { Left, Right, Icon } from 'native-base';
import { createStackNavigator } from 'react-navigation-stack';
class SplashScreen extends React.Component{
componentDidMount()
{
setTimeout(() => {
this.props.navigation.navigate('Login')
}, 4000);
}
render(){
return(
<View style={styles.Logocontainer}>
<Image
source={{uri: 'LOGO IMAGE HERE'}}
style={styles.logo} />
<ActivityIndicator size="large" color="blue" style={{margin:10}}/>
</View>
);
}
}
class Login extends React.Component{
login(){
const {username, password} = this.state;
Alert.alert('Login Successful');
this.props.navigation.navigate('Home');
}
render(){
return(
<View style={styles.Logocontainer}>
<Image
source={{uri: 'LOGO IMAGE HERE'}}
style={styles.logo} />
<Text style={{textAlign:'left',fontSize:25,color: '#009999'}}> Sign In {"\n"}</Text>
<TextInput
onChangeText={(username) => this.setState({ username })}
placeholder = "Username"
style={styles.input}
/>
<TextInput
onChangeText={(password) => this.setState({ password })}
placeholder = "Password"
style={styles.input}
secureTextEntry={true} />
<TouchableOpacity style={styles.button} onPress={this.login.bind(this)}>
<Text style={styles.loginbtn}> Login </Text>
</TouchableOpacity>
</View>
);
}
}
class Home extends React.Component{
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={{uri:'http://imageholder.freeasphost.net/home.png'}}
style={[styles.icon, { tintColor: tintColor }]}
/>
),
};
render()
{
return(
<View style={styles.container}>
<Header
leftComponent={<Icon name="menu" onPress={() => this.props.navigation.openDrawer()} />}
/>
<View style={styles.text}>
<Text> Welcome to Home screen</Text>
</View>
</View>
);
}
}
class Profile extends React.Component{
static navigationOptions = {
drawerLabel: 'Profile',
drawerIcon: ({ tintColor }) => (
<Image
source={{uri:'http://imageholder.freeasphost.net/profile.png'}}
style={[styles.icon, { tintColor: tintColor }]}
/>
),
};
render()
{
return(
<View style={styles.container}>
<Header
leftComponent={<Icon name="menu" onPress={() => this.props.navigation.openDrawer()} />}
/>
<View style={styles.text}>
<Text>Welcome to Profile screen</Text>
</View>
</View>
);
}
}
class Settings extends React.Component{
static navigationOptions = {
drawerLabel: 'Settings',
drawerIcon: ({ tintColor }) => (
<Image
source={{uri:'http://imageholder.freeasphost.net/settings.png'}}
style={[styles.icon, { tintColor: tintColor }]}
/>
),
};
render()
{
return(
<View style={styles.container}>
<Header
leftComponent={<Icon name="menu" onPress={() => this.props.navigation.openDrawer()} />}
/>
<View style={styles.text}>
<Text>Welcome to Settings Screen</Text>
</View>
</View>
);
}
}
const myStackNavigator = createStackNavigator({
SplashScreen:{
screen:SplashScreen
},
Login:{
screen:Login
},
});
const MyDrawerNavigator = createDrawerNavigator({
Home:{
screen:Home
},
Settings:{
screen:Settings
},
Profile:{
screen:Profile
},
});
const MyApp = createAppContainer(MyDrawerNavigator);
const MyPrologue = createAppContainer(myStackNavigator);
export default class App extends Component {
render() {
return (
<MyPrologue/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
container: {
flex: 1
},
text:{
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
Logocontainer:{
flex: 1,
justifyContent :"center",
alignItems:"center"
},
logo:{
width:150,
height:150
},
button:{
width:300,
padding:10,
backgroundColor:'#009999',
alignItems: 'center'
},
input: {
width: 300,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: '#009999',
marginBottom: 10,
},
loginbtn:{
color:'#ffff'
},
});

For this cases i would suggest to use a SwitchNavigator, that renders pretty much like a web application. When you are passing from one screen the previous screen gets unmounted. Only the focused screen will be mounted.
I'll keep your current StackNavigator if you wanted to use it for the header:
First of all you need to import the SwitchNavigator:
import { createSwitchNavigator } from 'react-navigation';
Remove const MyApp = createAppContainer(MyDrawerNavigator); and change
const MyPrologue = createAppContainer(myStackNavigator);
to
const MyPrologue = createAppContainer(switchNavigator );
where switchNavigator is :
const switchNavigator = createSwitchNavigator({
Authentication: {
screen:myStackNavigator
},
DrawerNavigator: {
screen: MyDrawerNavigator
},
},
{
initialRouteName: "Authentication"
})
Then your login function can navigate doing :
this.props.navigation.navigate("DrawerNavigator")
You can read about SwitchNavigator at : https://reactnavigation.org/docs/en/switch-navigator.html#docsNav

Related

Hamburger icon refuses to show in react-native

So i started to play with Navigation in React-native and i am really having fun with it, Except i ran into deadlocks with using the navigation in a way. Now here is what the worry is.
I want the header displayed using the hamburger icon. So the user can click the Hamburger Icon and it shows the menu on the Left where the user can select and perform any task, i tried it and it never shows up.
My code looks thus :
App.js
import React , {Component} from 'react';
import { View, Text, Image , StyleSheet } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createDrawerNavigator } from 'react-navigation-drawer';
import HamburgerIconMain from './HamburgerIcon/hamburgerIconMain';
class Home extends React.Component{
static navigationOptions = () => {
return{
headerLeft:<HamburgerIconMain/>
};
};
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={{uri:'http://imageholder.freeasphost.net/home.png'}}
style={[styles.icon, { tintColor: tintColor }]}
/>
),
};
render()
{
return(
<View>
<Text> Welcome to Home screen</Text>
</View>
);
}
}
class Profile extends React.Component{
static navigationOptions = {
drawerLabel: 'Profile',
drawerIcon: ({ tintColor }) => (
<Image
source={{uri:'http://imageholder.freeasphost.net/profile.png'}}
style={[styles.icon, { tintColor: tintColor }]}
/>
),
};
render()
{
return(
<View>
<Text>Welcome to Profile screen</Text>
</View>
);
}
}
class Settings extends React.Component{
static navigationOptions = {
drawerLabel: 'Settings',
drawerIcon: ({ tintColor }) => (
<Image
source={{uri:'http://imageholder.freeasphost.net/settings.png'}}
style={[styles.icon, { tintColor: tintColor }]}
/>
),
};
render()
{
return(
<View>
<Text>Welcome to Settings Screen</Text>
</View>
);
}
}
const MyDrawerNavigator = createDrawerNavigator({
Home:{
screen:Home
},
Settings:{
screen:Settings
},
Profile:{
screen:Profile
},
});
const MyApp = createAppContainer(MyDrawerNavigator);
export default class App extends Component {
render() {
return (
<MyApp/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
Then the code for the Hamburger icon looks like this
import React, {Component} from 'react';
import { withNavigation } from 'react-navigation';
import { TouchableOpacity } from "react-native-gesture-handler";
import Icon from 'react-native-vector-icons/SimpleLineIcons';
class HamburgerIconMain extends React.Component{
render(){
return(
<TouchableOpacity>
style={{
width: 44,
height: 44,
marginLeft: 20
}}
onPress={()=>{
this.props.navigation.openDrawer();
}}>
<Icon name='menu' size={20} color='black'/>
</TouchableOpacity>
);
}
}
export default withNavigation(HamburgerIconMain);
The worry I have now is , the header with the Hamburger Icon never shows up. How and what can i do to Resolve this
https://reactnavigation.org/docs/en/next/stack-navigator.html#docsNav
According to docs, you need to createStackNavigator.
Or, you can create your own header for Home screen with <HamburgerIconMain/> component.
Something like this.
render(){
return(
<View style={{flex:1, backgroundColor: 'green'}}>
<View style={{backgroundColor: 'yellow', height: 40, justifyContent: 'center'}}>
<Text> Header: add hamburger icon here </Text>
</View>
<View style={{flex: 1, backgroundColor: 'grey', justifyContent: 'center', alignItems: 'center'}}>
<Text> Welcome to Home screen</Text>
</View>
</View>
);
}
But such solution good just in case, if you want to see header just on one screen.

How to add arrow-back button inside Drawer Navigator to close the Drawer when opened

I'm trying to add arrow-back button INSIDE drawer, in top-right, which close the drawer onPress. I'm not sure am I doing it right way? Or I should put a Stack Navigator as header inside the Drawer ? I'll be glad if someone help me.
I'm using react-navigation V3.
Here is my code:
import React from 'react';
import { Platform, Dimensions, View, Text, StyleSheet } from 'react-native';
import { createDrawerNavigator, createAppContainer, DrawerItems } from 'react-navigation';
import {Header, Button} from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import Header2 from './Header2'
class MenuButton1 extends React.Component {
render () {
const { onDrawerOpen } = this.props;
return (
<React.Fragment>
<Button
icon={
<Icon
name="bars"
size={30}
color="white"
/>
}
onPress={() => onDrawerOpen()}
/>
</React.Fragment>
)
}
}
class HomeScreen extends React.Component {
render(){
return (
<React.Fragment>
<Header
leftComponent={
<MenuButton1 onDrawerOpen = {() => this.props.navigation.openDrawer()}/>
}/>
<View style={{top: 30 }}>
<Text> Hello </Text>
</View>
</React.Fragment>
);
}
}
const CustomDrawerContentComponent = (props) => (
<View style={{top:40}}>
<Header
leftComponent={
<Button
icon={
<Icon
name="arrow-left"
size={30}
color="black"
/>
}
onPress= {() => this.props.navigation.closeDrawer()}/>}
/>
<Text>Custom Header</Text>
<DrawerItems {...props} />
</View>
),
WIDTF = Dimensions.get('window').width;
const DrawerConfig = {
drawerWidth: WIDTF*0.80,
draertType: 'slide'
}
const Drawer = createDrawerNavigator ({
Home: {
screen: HomeScreen
},
About: {
screen: Header2
}
},
DrawerConfig,
{
contentComponent: CustomDrawerContentComponent
});
export default createAppContainer (Drawer);
enter image description here
But it doesn't appear.
Here it is you can use Header with default components like:
<Header
leftComponent={{ icon: 'menu', color: '#fff' }}
centerComponent={{ text: 'MY TITLE', style: { color: '#fff' } }}
rightComponent={{ icon: 'home', color: '#fff' }}
/>
as mentioned here
Or you can do something like this:
import {NavigationActions} from 'react-navigation'; //add this import to the Navigator.js file
const DrawerNavigators = createDrawerNavigator({
Home:{
screen: Home ,
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: 'black',
headerTintColor: '#ffffff',
tintColor: {
color: '#ffffff'
},
headerTitleStyle: { color: 'black' }
},
}),
}
},{
initialRouteName: 'Home',
contentComponent: Drawers,
drawerWidth: 300
});
DrawerNavigators: {
screen: DrawerNavigators,
navigationOptions: ({ navigation }) => ({
headerTintColor: '#ffffff',
headerStyle: {
backgroundColor: 'black',
title: 'Home',
},
headerLeft:
<View style={{flex:1, flexDirection:'row'}}>
<TouchableOpacity onPress={() =>
navigation.toggleDrawer()
}>
<Image style = {{margin :15 ,height :30 ,width :30}}
source={require('./resources/menu.png')} />
</TouchableOpacity>
<TouchableOpacity onPress={()=> navigation.navigate('Home')}>
<Text style={{width: 200, fontSize:15,padding:10, color:'white',marginTop:8}}>Home</Text>
</TouchableOpacity>
</View>
,
}),
},
Now create a Drawers.js file
import React, {Component} from 'react';
import {NavigationActions,StackActions} from 'react-navigation';
import PropTypes from 'prop-types';
import {ScrollView, Text, View ,AsyncStorage,Image,TouchableOpacity} from 'react-native';
import { DrawerActions } from 'react-navigation';
import styles from './Style.js'
class Drawer extends Component {
constructor(props){
super(props)
const { navigation } = this.props;
this.state = {
my: '',
}
}
render () {
return (
<View style={{flex:1}}>
<ScrollView>
<View style={styles.headertop}>
<Image style={ styles.thumbnail } source={require('./resources/images.png')} />
<Text style={styles.headertext}>Username</Text>
<Text style={{fontSize:13, color:'white',marginTop:40, marginLeft:155}}>Wallet Balance:</Text>
<Text style={{fontSize:13, color:'white', marginTop:-20, marginLeft:260}}>$0.00</Text>
</View>
<TouchableOpacity onPress={() => this.props.navigation.navigate('MyProfile')}>
<View style={styles.menuItem}>
<Image style={styles.drawericon}
source={require('./resources/prof.png')} />
<Text style = {styles.drawerText} >
My Profile
</Text>
</View>
</TouchableOpacity>
</ScrollView>
</View>
);
}
}
Drawer.propTypes = {
navigation: PropTypes.object
};
export default Drawer;

undefined is not an object (evaluating'_this2.props.navigation.navigate') - React Native

I am having trouble navigating through screens with a simple button.
This is my App.js
export default class App extends Component<Props> {
render() {
return (
<AppStackNavigator/>
);
}
}
const AppStackNavigator = StackNavigator({
Login: { screen: LoginScreen },
Home: { screen: HomeScreen },
},{
navigationOptions: {
gesturesEnabled:false
}
})
Login.js
export default class Login extends Component {
render() {
return(
<SafeAreaView style={styles.container}>
<StatusBar barStyle='light-content'/>
<KeyboardAvoidingView behavior='padding' style={styles.container}>
<TouchableWithoutFeedback style={styles.container} onPress={Keyboard.dismiss}>
<View style={styles.logoContainer}>
<View style={styles.logoContainer}>
<Image style={styles.logo}
source={require('../images/logo/logo.png')}>
</Image>
<Text style={styles.title}>
Sports Chat App
</Text>
</View>
<View style={styles.infoContainer}>
<TextInput style={styles.input}
placeholder="Enter name"
placeholderTextColor='#ffffff'
keyboardType='default'
returnKeyType='next'
autoCorrect={false}
onSubmitEditing={()=> this.refs.phoneNumber.focus()}
/>
<TextInput style={styles.input}
placeholder="Enter phone number"
placeholderTextColor='#ffffff'
keyboardType='phone-pad'
ref={'phoneNumber'}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Button title='LogIn' onPress={()=>this.props.navigation.navigate('Home')}/>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</SafeAreaView>
)
}
};
LoginScreen.js
class LoginScreen extends Component {
render(){
return (
<View>
<Login>
</Login>
</View>
);
}
}
I keep getting the error undefined is not an object (evaluating'_this2.props.navigation.navigate') whenever i try use the Login button in Login.js,
I want this to navigate to the home screen but cant figure out why this keeps happening.
If i try do it without the components it works fine.
Click to View error message
Add a navigation props to Login in LoginScreen.js, Because LoginScreen has props navigation but Login don't.
render(){
return (
<View>
<Login navigation ={this.props.navigation}>
</Login>
</View>
);
}
App.js
import React, { Component } from "react";
import { Text, View } from "react-native";
import AppStackNavigator from "./AppStackNavigator";
export default class App extends Component<Props> {
render() {
return <AppStackNavigator />;
}
}
AppStackNavigator
import React, { Component } from "react";
import { StackNavigator } from "react-navigation";
import { View, Text, TouchableOpacity } from "react-native";
const LoginScreen = props => (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Login navigation={props.navigation} />
</View>
);
const HomeScreen = () => (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Home</Text>
</View>
);
const Login = props => (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<TouchableOpacity
onPress={() => {
props.navigation.navigate("Home");
}}
>
<Text>GO to home from login</Text>
</TouchableOpacity>
</View>
);
export default (AppStackNavigator = StackNavigator(
{
Login: { screen: LoginScreen },
Home: { screen: HomeScreen }
},
{
headerMode: "none",
navigationOptions: {
gesturesEnabled: false
}
}
));
You need to access the navigation prop in the component. Check the official guide.
reactnavigation Official guide
import React from 'react';
import { Button } from 'react-native';
import { withNavigation } from 'react-navigation';
class MyBackButton extends React.Component {
render() {
return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
}
}
// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);

undefined is not an object (evaluting_'this2.pros.navigation')

App.js
import {DrawerNavigator} from 'react-navigation';
import SettingsScreen from './src/components/SettingsScreen';
import UploadsScreen from './src/components/UploadsScreen';
const DrawerExample = DrawerNavigator(
{
First:{
path:'/',
screen:UploadsScreen,
},
Second:{
path:'/sent',
screen:SettingsScreen,
},
},
{
initialRouteName:'First',
DrawerPosition:'left'
}
);
export default DrawerExample;
2.SettingScreen.js
export default class SettingsScreen extends Component{
static navigationOptions ={
tabBarLabel: 'Screen1',
drawerIcons: () =>{
return (
<Image style={{width:5, height:5}}
source={require('../images/notification-icon.png')} />
);
}
}
render(){
return <View style={
{
flex:1,
justifyContent:'center',
alignItems:'center'
}
}>
<Text style={{fontSize:30, color:'green'}}>
Screen1
</Text>
<Button
onPress={() => this.pros.navigation.navigate('DrawerOpen')}
title="Open DrawNavigator"
/>
</View>
}
}
3.Uploadscreen.js
export default class UploadsScreen extends Component{
static navigationOptions ={
tabBarLabel: 'Screen2',
drawerIcons: () =>{
return (
<Image style={{width:5, height:5}}
source={require('../images/home-icon.png')} />
);
}
}
render
(){
return <View style={
{
flex:1,
justifyContent:'center',
alignItems:'center'
}
}>
<Text style={{fontSize:30, color:'blue'}}>
Screen1
</Text>
<Button
onPress={() => this.pros.navigation.navigate('DrawerOpen')}
title="Open DrawNavigator"
/>
</View>
}
}
navigating to any page it shows the same error undefined is not an
object (evaluting_'this2.pros.navigation') while trying the other
method routing flux it show the same and in drawer navigation its
same i am stuck Anybody knws the solution please let me knw....

undefined is not a function(evaluating '_navigationactions2.default.reset')

I am new to react native, I just follow react navigation official docs and try to use drawerNavigator and stackNavigator.
When I access drawerNavigator from the second screen of stackNavigator shows error: undefined is not a function(evaluating '_navigationactions2.default.reset').
Simply said, how can I access drawer from anywhere.
Here is App.js:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, {Component} from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Button,
Image
} from 'react-native';
import {createStackNavigator, createDrawerNavigator} from 'react-navigation';
class HomeScreen extends React.Component {
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
this.props.navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
}
class DetailsScreen extends React.Component {
render() {
/* 2. Read the params from the navigation state */
const {params} = this.props.navigation.state;
const itemId = params ? params.itemId : null;
const otherParam = params ? params.otherParam : null;
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.navigate('Details')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
class MyHomeScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'DrawerHome',
drawerIcon: ({tintColor}) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Notifications',
drawerIcon: ({tintColor}) => (
<Image
source={require('./notif-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
const RootStack = createStackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
}
);
const MyApp = createDrawerNavigator({
Home: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
Stack: {
screen: RootStack,
}
}
);
export default class App extends React.Component {
render() {
return <MyApp/>;
}
}
react version: 16.3.1
react-native version: 0.55.3
Please help me.
error from AVD, android version: 6.0
https://i.stack.imgur.com/WDTyY.png