React navigation 5 : Pass arguments with Navigation - react-native

I am using class components with react navigation5 and I have two classes :
Class DrawerComponent.js
export default class DrawerContent extends Component{
constructor(props){
super(props);
}
render(){
return(
<View style={{flex:1}}>
<DrawerContentScrollView {...this.props}>
<Drawer.Section style={styles.drawerSection}>
{
<DrawerItem
icon={({color,size}) => (
<Icon
name=""
color={color}
size={size}
/>
)}
label={menu.localizedTitle}
onPress = {() =>**{this.props.navigation.navigate("RecordList",{body :'abc' }**)}}/>)
</Drawer.Section>
</View>
</DrawerContentScrollView>
</View>
)}}
Now if I have to access value of body in another class, how can I do so?

in your RecordList component, you can access the params with route
const RecordList = ({navigation, route})=>{
const {body} = route.params;
console.log(body)
}
in class based component:
class RecordList extends Component{
render(){
const {body} = this.props.route.params;
console.log(body)
return <View><Text>{body}</Text></View>
}
}

I am using stackNavigator inside drawerNavigator so I will have to use nested navigation:
this.props.navigation.navigate('RecordList', {screen:'Home',params :{ title: "Home"}})
and retrieving can be done exactly like how it is done above in Ketan's answer.

Related

Access to this.props.navigation on Header Component

I have an ApplicationHeader Component and I want to navigate to a specific screen on touch, but I'm getting
undefined is not an object (evaluating this.props.navigation.navigate)
App.js
render() {
return (
<SafeAreaView forceInset={{ bottom: 'never' }} style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<Provider store={store}>
<ApplicationHeader navigation={this.props.navigation} />
<AppNavigator />
</Provider>
</SafeAreaView>
);
}
ApplicationHeader.js
class ApplicationHeader extends Component {
constructor(props) {
super(props)
}
openWishlist() {
this.props.navigation.navigate('Wishlist')
}
render() {
const { isLogged } = this.props;
return (
<View style={AppStyle.header}>
<TouchableOpacity onPress={() => this.openWishlist()}>
{!isLogged && (<Image source={imgWishList} style={AppStyle.headerWishlist} />)}
{isLogged && (<Image source={imgWishListLogged} style={AppStyle.headerWishlist} />)}
</TouchableOpacity>
</View>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ApplicationHeader);
It seems like that your HeaderComponent is might not be in Navigation Stack.
In that case, you can try the following solution:
First import withNavigation in your file like
import { withNavigation } from 'react-navigation';
After that change your component export to
export default connect(
mapStateToProps,
mapDispatchToProps
)(withNavigation(ApplicationHeader));
So you will get the access to navigation pros in this component.
Also your ApplicationHeader can move to inner container components. It shouldn't have to be in App.js to use the navigation props.
Hope this will help you.

React Native can't find variable: navigate

I am doing stack navigation but I can't seem to be able to navigate I will get this error "Can't find variable: navigate" Here is the screenshot of my android emulator
This is my App class(main)
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Header/>
<AppNavigator/>
</View>
);
}
}
const AppNavigator = StackNavigator({
Cluster1: {
screen: Cluster1,
},
Play: {
screen: Play,
},
});
This is my Cluster1 class
export default class Cluster1 extends Component{
render(){
return(
<View>
<SectionList
renderSectionHeader={({ section }) => {
return (<SectionHeader section={section} />);
}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}
>
</SectionList>
</View>
);
}
}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={() => { navigate("Play");}}>
<Text style ={styles.Play}>Play
</Text>
</TouchableOpacity>
</View>
);
}
}
navigation object only exist in the screen component. (not exist in the nested components). you can pass it into the nested component using props
export default class Cluster1 extends Component{
render(){
return(
<View>
<SectionList
renderSectionHeader={({ section }) => {
return (<SectionHeader navigation={this.props.navigation} section={section} />);
}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}
>
</SectionList>
</View>
);
}
}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={() => { this.props.navigation.navigate("Play");}}>
<Text style ={styles.Play}>Play
</Text>
</TouchableOpacity>
</View>
);
}
}
Include on your SectionHeader the this.props.navigation something like this:
<SectionHeader navigation={this.props.navigation}/>
because the props.navigation are by default on your parent component
and on SectionHeader component you will access to navition like:
..
goToSignUp() {
this.props.navigation.navigate('SignUp');
}
..
For me also was confusing before. Cheers!
You can use this rather than navigate :
this.props.navigation.navigate('Play')
Hope this is helpful.

react-navigation not working, props is undefined

I am building a POC application in react-native and trying to implement react-navigation
import {StackNavigator, DrawerNavigator} from 'react-navigation';
export default class HomeScreen extends React.Component {
constructor(props) {
super(props)
this.clicked = this.clicked.bind(this)
}
static navigationOptions = {
drawerLabel: 'Home',
};
clicked = ()=> {
this.props.navigator.navigate('DrawerOpen'); // open drawer
}
render() {
// const {navigate} = this.props.navigation;
return (
<ScrollView>
<View style={styles.container}>
<View style={styles.header}>
<View style={{width: 50}}>
<TouchableHighlight onPress={()=> {
this.clicked("DrawerOpen")
}}>
<Image source={require('./img/hamburger_icon.png')}/>
</TouchableHighlight>
</View>
</View>
</View>
</ScrollView >
)
}
}
Now whenever I am clicking on touchable highlight, clicked function gets called and it shows error:
undefined is not an object (evaluating '_this.props.navigator.navigate')
clicked
You try it :)
import {StackNavigator, DrawerNavigator} from 'react-navigation';
export default class HomeScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Home',
};
clicked = () => {
this.props.navigation.navigate('DrawerOpen'); // open drawer
}
render() {
// const {navigate} = this.props.navigation;
return (
<ScrollView>
<View style={styles.container}>
<View style={styles.header}>
<View style={{width: 50}}>
<TouchableHighlight onPress={()=>
this.clicked()
}>
<Image source={require('./img/hamburger_icon.png')}/>
</TouchableHighlight>
</View>
</View>
</View>
</ScrollView >
)
}
}
Try this , May be this can help you, Inside the clicked
clicked = ()=> {
this.props.navigation.navigate('DrawerOpen');
}
This just happened to me. Only the top level components get the this.props.navigation.
Probably you have to call this component like this:
<HomeScreen navigation=this.props.navigation />

Getting undefined is not an object (evaluating '_this.props.navigation')

I'm using DrawerNavigator and I have 3 pages: Router page, mainScreen and a photos page.
I maked a header navbar area and I used This <TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}> to open Drawer menu in mainScreen and used that for photos page too, menu is ok in mainScreen but when I click <TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}> in photos page, I get the error:
undefined is not an object (evaluating '_this.props.navigation')
How can I fix that?
My photos page:
import React from 'react';
import { Button, ScrollView, View, Text, StyleSheet, TouchableHighlight } from 'react-native';
import { DrawerNavigator } from 'react-navigation';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import Icon from 'react-native-vector-icons/FontAwesome'
const MyNavScreen = ({ navigation }) => (
<View>
<View style={styles.containerNavbar}>
<TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}>
<Icon name="bars" size={30} color="#fff" />
</TouchableHighlight>
<Text style={styles.navbarTitle}>Photos</Text>
</View>
<ScrollView>
<View><Text>photo</Text></View>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</ScrollView>
</View>
);
const MyPhotosHomeScreen = ({ navigation }) => (
<MyNavScreen navigation={navigation} />
);
MyPhotosHomeScreen.navigationOptions = {
title: 'Photos',
drawerIcon: ({ tintColor }) => (
<MaterialIcons
name="photo"
size={24}
style={{ color: tintColor }}
/>
),
};
export default MyPhotosHomeScreen;
mainScreen:
export default class MainScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<MaterialIcons
name="home"
size={24}
style={{ color: tintColor }}
/>
)
};
render() {
return (
<View>
<View style={styles.containerNavbar}>
<TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}>
<Icon name="bars" size={30} color="#fff" />
</TouchableHighlight>
<Text style={styles.navbarTitle}>mainScreen</Text>
</View>
<View>
<View style={styles.containerFooter}>
<Text style={styles.footerTitle}>Footer</Text>
</View>
</View>
</View>
)
}
}
If you are using navigation in child component don't forget to send navigation in props to child
<ChildComponent navigation={this.props.navigation}/>
Access in child component like this
props.navigation.navigate("ScreenName")
Perhaps I'm overlooking something, but it just looks like a simple Javascript error. You're destructing your props in your pure component MyNavScreen:
const MyNavScreen = ({ navigation }) => (
This means that you don't have access to this.props. You just have access to the destructured prop navigation. Hence the reason for the undefined error as this really is undefined:
<TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}>
If you change it instead to use navigation directly, it should work:
<TouchableHighlight onPress={() => navigation.navigate('DrawerOpen')}>
On mainScreen, you are fine because it's not a pure component with destructured arguments. So you still have access to this.props in render().
You should brush up on destructing if this is causing you trouble.
Binding this worked for me
In my case it worked when I bind this to the method that calls the prop it in the constructor.
constructor(props){
super(props);
this.showDetails = this.showDetails.bind(this);// you should bind this to the method that call the props
}
showDetails(_id){
this.props.navigation.navigate('Details');
}
for functional components try useNavigation hook for deep navigation
Or Simply use arrow function
showDetails = (_id) => {
this.props.navigation.navigate('Details');
}
because while you use expression function it is going to create it's own scope.
Try this:
import { withNavigation } from 'react-navigation';
withNavigation serves the props all over the project/app, you access the navigation props from anywhere.
and
onPress={() => this.props.navigation.navigate('DrawerOpen')}
Finally,
export default withNavigation(MyPhotosHomeScreen);
check out this https://reactnavigation.org/docs/en/connecting-navigation-prop.html
If you use TouchableOpacity/Height in your child element, pass it this.props.onPress like this:
<TouchableOpacity onPress={this.props.onPress}/>
Then call the onPress function in your parent component like this:
<Parent onPress={this.Handlepress} />
very simple: follow some steps here
import {useNavigation} from '#react-navigation/native';
const Home =()=>{
//add this line under function scope.
const navigation = useNavigation();
return(
<TouchableOpacity onPress={() => navigation.navigate('Detail')}>
//your code.......................
)
}
This is how I have done it in React Navigation 2 release: I call the openDrawer() method from a StackNavigator that is a child navigator of the DrawerNavigator.
This is my DrawerNavigator:
export const Drawer = DrawerNavigator(
{
MyAccount: {screen: TabsStack},
});
export const TabsStack = StackNavigator({
Tabs: {
screen: Tabs, navigationOptions: ({navigation}) => ({
headerLeft: (
<TouchableOpacity style={{marginLeft: 10, marginTop: 3}}
onPress={() => navigation.openDrawer()}>
<Image source={require('./assets/menu_h.png')}/>
</TouchableOpacity>)
})
functional components take props as argument.
You should try this
const MyNavScreen = ({props}) =>
and then call the props without this key word
onPress = {() => props.navigation.navigate('DrawerOpen')}
If you want navigation in child component,then you have to get props in child component.
Suppose you have 3 components - Comp_1,Comp_2,Comp_3 and you want to navigate from Comp_2 -> Comp_3. To do this follow these steps.
Pass props in Comp_1 component.Like this
<Comp_2 navigation={this.props.navigation}/>
Now in Comp_2, we can navigate from Comp_2 -> Comp_3 like this.
this.props.navigation.navigate('Comp_3');
For example -
<Button
onPress = {() => this.props.navigation.navigate('Comp_3')}
title = 'Go to Comp_3 Screen'
/>
In then compnent that you're trying enter to another view you must send the object navigation by you use this in the onPress of component imported
example
Implementing component in a view
<CardComponent title="bla bla" navigation={this.props.navigation} />
Component template
<View>
<Button title={this.props.title} onPress={()=>
this.props.navigation.navigate("anotherAwesomeView")}/>
</View>
This problem is because the component that you're trying implement is not defined on stackNavigation, and by this the methot navigation is not avalible for you, and passing this object navigator by params you'll can access to it
For those who are not using class components and prefer functional components:
First import useNavigation then from the screen that you wish to navigate from, initiate (declare) the variable navigation = useNavigation();
import { useNavigation } from '#react-navigation/native';
function ScreenToNavigateFrom() {
const navigation = useNavigation();
return(
<TouchableOpacity onPress={() => navigation.navigate('AnotherScreen')}>
<Text style={{fontWeight: "bold", color:"white" }} >Performance</Text>
</TouchableOpacity>
);
}
This answer is courtesy of this gisthub issue: https://github.com/react-navigation/react-navigation/issues/7961
i had the same problem when i was using the header component
now you can use the navigation variable in other component like this
<TouchableOpacity onPress={() => { this.props.navigation.navigate("Play");}}>
Happy Codding :)
try this instead you might be missing to import useNavigation() from '#react-navigation/native';
import { useNavigation } from '#react-navigation/native';
function NotificationsScreen() {
const navigation = useNavigation();
return(
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
enter code here
I encountered the same problem. That's how I solved it:
Verify that all your constructors have "props" has argument
Bind the function with use the function this.props.navigation.navigate in the constructor like this: this.your_function = this.your_function.bind(this)
when you defined screen in createStackNavigator , it by default pass a props called navigation,
something like this => navigation={this.props.navigation}
but when you using this.props.navigation.navigator("YOUR SCREEN ")
and didn't defined this screen at createStackNavigator you must pass the navigation={this.props.navigation} form the screen that you defined in createStackNavigator and then you can use it in your component .
class ProductScreen extends Component {
export default ProductScreen; // make sure bottom this line mention
Call this
<TouchableOpacity
onPress = {() => this.props.navigation.navigate('ProductAddScreen')}
activeOpacity={0.7} style={styles.button}>
<Text style={styles.message}>{this.state.notFound} </Text>
</TouchableOpacity>

React Native and Drawer : undefined is not an object navigator

I want to set up a sidebar menu with Drawer (Native Base).
I have a App.js :
export default class ReactProject extends Component {
renderScene (route, navigator) {
return <route.component navigator={navigator} />
}
render() {
return (
<Navigator
style={styles.container}
renderScene={this.renderScene.bind(this)}
initialRoute={{component: Home}}
/>
);
}
}
A Home.js with the drawer :
export default class Home extends Component {
render() {
return (
<Drawer
ref={(ref) => { this._drawer = ref; }}
content={<SideBar />} navigator={this.props.navigator}>
<Container>
</Container>
</Drawer>
);
}
}
And sidebar.js which is loaded into the drawer :
export default class SideBar extends Component {
constructor(props) {
super(props);
}
redirect(routeName){
this.props.navigator.push({
component: routeName
});
}
render() {
return (
<Content style={styles.sidebar}>
<ListItem button >
<Text>Home</Text>
</ListItem>
<ListItem button >
<Text>Test</Text>
</ListItem>
<ListItem button onPress={this.redirect.bind('Blank')}>
<Text>Blank Page</Text>
</ListItem>
</Content>
);
}
}
But when I click i have this error:
Undefined is not an object (evaluating 'this.props.navigator.push')
I do not have this problem when the button is in the page but only in the sidebar.js
Could someone help me?
thank you,
Thomas.
I think you have to change little bit code of your Home.js as per mentioned below:
render() {
return (
<Drawer
ref={(ref) => { this._drawer = ref; }}
content={<SideBar navigator={this.props.navigator} />}
<Container>
</Container>
</Drawer>
);
And add this lines of code in your sidebar.js file:
static propTypes = {
navigator: React.PropTypes.object,
}