DrawerNavigator - Can't open DrawerNavigator inside StackNavigator route - react-native

recently I have a problem on a simple DrawerNavigator inside StackNavigator. My goal is to get both the back function from StackNavigator and DrawerNavigator side menu when I click BurgerMenu icon on the StackNavigator's header.
Here's my current code
import React, { Component } from 'react';
import { TouchableHighlight } from 'react-native';
import SvgUri from 'react-native-svg-uri';
import { StackNavigator } from 'react-navigation';
import { DrawerNavigator } from "react-navigation";
import SideBar from './SideBar';
import Screen1 from './Screen1';
import Screen2 from './Screen2';
import Screen3 from './Screen3';
export default class App extends React.Component {
render() {
return <StackNav />;
}
}
class BurgerMenu extends React.Component {
render() {
return (
<TouchableHighlight
onPress={() => this.props.navigation.navigate("DrawerOpen")}>
<SvgUri
width="30"
height="30"
source={require("Project_01/app/images/menu.svg")}
/>
</TouchableHighlight>
);
}
}
const DrawerNav = DrawerNavigator(
{
Screen1: { screen: Screen1 }
},
{
contentComponent: props => <SideBar {...props} />
}
);
const StackNav = StackNavigator(
{
Screen1: {
screen: DrawerNav,
},
Screen2: {
screen: Screen2,
},
Screen3: {
screen: Screen3,
},
},
{
initialRouteName: 'DrawerNav',
navigationOptions: {
headerRight: <BurgerMenu /> ,
title: "Header"
},
},
);
As you can see Im adding headerRight with BurgerMenu component to navigationOptions in StackNavigator.
In BurgerMenu class I added TouchableHighlight with " onPress={() => this.props.navigation.navigate("DrawerOpen")}> " which I mean open up the DrawerNavigator.
Unfortunately when I press that, i got an error message says "undefined is not an object (evaluating 'e.props.navigation.navigate').
Can someone help me please

Try changing this:
navigationOptions: {
headerRight: <BurgerMenu /> ,
title: "Header"
},
by this:
navigationOptions: ({navigation}) => ({
headerRight: <BurgerMenu navigation={navigation} />,
title: "Header"
}),
Also you can refer to this example on my github.

Related

How to nest a component wrapping a stack navigator inside a tab navigator react

Current Behavior
I am trying to have a tab navigator, where one of the screens/tabs has a component, that, among other stuff, has a stack navigator in it.
However, I currently get a 'No "routes" found in navigation state' error.
How to reproduce
The code I'm currently running can also be found as a snack.
Code:
import * as React from 'react';
import { Button, Text, View, StyleSheet } from 'react-native';
import { createAppContainer, createStackNavigator, createBottomTabNavigator } from 'react-navigation';
class ScreenA extends React.Component {
static navigationOptions = {
tabBarLabel: 'A',
};
render() {
return (
<View>
<Text>Screen A</Text>
</View>
);
}
}
class SettingsHome extends React.Component {
render() {
return (
<Button onPress={() => this.props.navigation.navigate('SettingsScreenA')}>
<Text>Navigate to Settings A</Text>
</Button>
);
}
}
class SettingsScreenA extends React.Component {
render() {
return (
<View>
<Text>Settings A</Text>
<Button onPress={() => this.props.navigation.navigate('SettingsA')}>
<Text>Back to SettingsHome</Text>
</Button>
</View>
);
}
}
const SettingsStackNavigator = createStackNavigator({
SettingsHome: { screen: SettingsHome },
SettingsScreenA: { screen: SettingsScreenA }
})
class SettingsScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Settings',
}
render() {
return (
<View>
<Text>Some other components...</Text>
<SettingsStackNavigator navigation={this.props.navigation}/>
</View>
);
}
}
const RootTabNavigator = createBottomTabNavigator({
ScreenA: { screen: ScreenA },
Settings: {screen: SettingsScreen },
});
const Navigation = createAppContainer(RootTabNavigator);
export default class App extends React.Component {
render() {
return (
<Navigation />
);
}
}
in this button you want to navigate to SettingsA
<Button onPress={() => this.props.navigation.navigate('SettingsA')}>
<Text>Back to SettingsHome</Text>
</Button>
but you defined the route of Settings screen as Settings
const RootTabNavigator = createBottomTabNavigator({
ScreenA: { screen: ScreenA },
Settings: {screen: SettingsScreen },
});
you have to fix it by change the SettingsA as route name in tab navigator
const RootTabNavigator = createBottomTabNavigator({
ScreenA: { screen: ScreenA },
SettingsA: {screen: SettingsScreen },
});

undefined is not an object (evaluating '_this.props.navigation.navigate') upon button click

I am fairly new to react-native and react-navigation and trying to move from one screen to another via button click, keep getting this error. I've found similar questions here on SO (this and this) but they don't work for me, keep getting this error.
What I am doing is, I have an App.js that is the initial screen which for now shows a login form (called Splash):
import React from 'react';
import {
View,
ActivityIndicator,
StyleSheet
} from 'react-native';
import { createDrawerNavigator, createAppContainer } from "react-navigation";
import HomeScreen from './HomeScreen';
import ProfileScreen from './ProfileScreen';
import Splash from './Splash';
export default class App extends React.Component {
render() {
const { navigation } = this.props;
return (
<View>
<Splash navigation={navigation}/>
</View>
);
}
}
const AppNavigator = createDrawerNavigator({
Home: {
screen: HomeScreen
},
Profile: {
screen: ProfileScreen
}
}, {
initialRouteName: "Home",
contentOptions: {
activeTintColor: '#e91e63'
}
});
const AppContainer = createAppContainer(AppNavigator);
On my Splash screen I now have no functionality as I am just trying to get it to move to my HomeScreen when I hit the Login button:
import React, { Component } from 'react';
import {
ScrollView,
Text,
TextInput,
TouchableOpacity,
StyleSheet
} from 'react-native';
class Splash extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ScrollView style={{padding: 20}}>
<TextInput autoCapitalize="none"
onSubmitEditing={() => this.passwordInput.focus()}
autoCorrect={false}
keyboardType='email-address'
returnKeyType="next"
placeholder='Email address'
placeholderTextColor='rgba(225,225,225,0.7)'/>
<TextInput returnKeyType="go"
ref={(input)=> this.passwordInput = input}
placeholder='Password'
placeholderTextColor='rgba(225,225,225,0.7)'
secureTextEntry/>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Home')}>
<Text>LOGIN</Text>
</TouchableOpacity>
</ScrollView>
)
}
};
export default Splash;
What happens now is that as soon as I hit the login button, I get the error in the title. Any clues on what I am doing wrong?
Remove App component, you don't need it in this case. Make Splash as your initial screen
const AppNavigator = createDrawerNavigator({
Splash: {
screen: Splash
},
Home: {
screen: HomeScreen
},
Profile: {
screen: ProfileScreen
}
}, {
initialRouteName: "Splash",
contentOptions: {
activeTintColor: '#e91e63'
}
});
then export AppContainer directly
const AppContainer = createAppContainer(AppNavigator);
export default AppContainer

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

Navigate to a screen not defined with createBottomTabNavigator in React Native

I am trying to navigate to a screen that I have not defined with createBottomTabNavigation as I don't want it to be shown on the bottom tab navigation.
To try so I have created the component separately:
class SingleScreen extends React.Component {
render() {
return (
<View>
<Text>This is sigle screen</Text>
</View>
);
}
}
To navigate to this screen:
render () {
const {navigate} = this.props.navigation;
return(
<TouchableHighlight onPress={() => navigate('SingleScreen', {id: 'id', from: 'Search'})}>
//Code
</TouchableHighlight>
);
}
But is not working. Do I have to describe this screen with createBottomTabNavigator? If so, is it possible to hide from appearing on the tab bar?
You need to make some change in app.js. add createBottomTabNavigator inside createStackNavigator. Add those component into stacknavigator in which you do not want to add into bottom tab navigator. In createBottomTabNavigator add those component which you want to show in tab bar
Please check following code
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
SafeAreaView,
ScrollView,
Dimensions
} from "react-native";
import { createStackNavigator, createDrawerNavigator } from "react-navigation";
import LoginScreen from "./Screens/LoginScreen";
export default class App extends Component {
render() {
return <StackNav />;
}
}
const StackNav = createStackNavigator(
{
TabNavigator: {
screen: AppTabNavigator,
navigationOptions: {
headerMode: "none",
header: null
}
},
SingleScreen: {
screen: SingleScreen,
navigationOptions: {
headerMode: "none",
header: null
}
},
SecondScreen: {
screen: SecondScreen,
navigationOptions: {
headerMode: "none",
header: null
}
}
},
{
initialRouteName: "TabNavigator"
}
);
const AppTabNavigator = createBottomTabNavigator({
Login: {
screen: LoginScreen
}
});

Dynamically change header title in react native navigation

For a school assignment we're creating an app in react native with react navigation and redux. Because all of us are new to react we have an issue we are unable to resolve.
We want to change the title of the header when a certain button is clicked. The first time we click a button it changes the header title just fine. The problem arrises when we press a different button, the header doesn't change. Note that no matter what option we choose, we always go to the same screen.
import React from 'react';
import { createStackNavigator, createAppContainer, createDrawerNavigator } from 'react-navigation';
import {connect} from 'react-redux';
import { store } from '#redux/MyStore';
import { Ionicons } from '#expo/vector-icons';
import ScannerScreen from '#screens/ContactScreen';
import EventsScreen from '#screens/ListScreen';
const ContactStack = createStackNavigator({
Contact: {
screen: ContactScreen,
navigationOptions: ({navigation}) => ({
headerStyle: {backgroundColor: '#fa8231'},
headerTitleStyle: {fontSize: 18},
title: store.getState().setupState.title,
headerLeft: <Ionicons
name="md-menu" style={{marginLeft:10}}
size={28}
onPress={() => navigation.toggleDrawer()} /> //menu button
})
}
});
// Code to create stack for the ListStack
const DrawerStack = createDrawerNavigator({
Contact: ContactStack,
List: ListStack
});
const PrimaryNavigation = createStackNavigator({
ListStack: {
screen: ListStack,
navigationOptions: {
header: null,
},
},
DrawerStack: {
screen: DrawerStack,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'ListStack',
});
const AppContainer = createAppContainer(PrimaryNavigation);
class AppNavigation extends React.Component {
render() {
return <AppContainer/>
}
}
export default (AppNavigation)
We did get it working when we put the title bar in the DrawerNavigator, but since we want the Drawer in from of the header that is not an option. My speculation is that the stack is created once with a certain title and never gets updated when switching screens using the DrawerNavigator but we have no clue how to fix that.
Thanks in advance!
From what I understand you need to change the title when a screen is loaded in stack.So you could use some like:
class ScreenInContactStack extends React.Component{
//Constryctor
static navigationOptions = ({navigation}) => ({
title: (navigation.state.params || {}).title || 'Chat! ',
});
//Remaining Logic
}
and while calling
this.props.navigation.navigate('ScreenInContactStack', {title: yourTitle + ' ',});
Don't know why but the Appbar condense the title to like yourTi.. to avoid this add a space to the title.
Try this:
map title as a prop to force ContactStack to re-render whenever it changes
class ContactStack extends React.Component {
render() {
const { title } = this.props.setupState;
const Stack = createStackNavigator({
Contact: {
screen: ContactScreen,
navigationOptions: ({navigation}) => ({
headerStyle: {backgroundColor: '#fa8231'},
headerTitleStyle: {fontSize: 18},
title,
headerLeft: <Ionicons
name="md-menu" style={{marginLeft:10}}
size={28}
onPress={() => navigation.toggleDrawer()} /> //menu button
})
}
});
return <Stack />;
}
}
const mapStateToProps = ({ setupState }) => ({setupState});
export default connect(mapStateToProps)(ContactStack);