Undefined is not an object (Evaluating this.props.navigation.navigate) in reactnative - react-native

Good day.
I tried navigating to another page using reactnative navigation but it is displaying "Undefined is not an object (Evaluating this.props.navigation.navigate) in reactnative"
This is my code
import React, { Component } from 'react';
import {Text, View, Image, Alert} from 'react-native';
import { Icon, Button, List, ListItem, Left, Thumbnail, Body, Right } from 'native-base';
import {styles} from '../../../css/Designs';
import OptionsMenu from "react-native-options-menu";
const myIcon = (<Icon name='more' style={{fontSize:30,color:'#000'}}/>);
export class TheStudent extends Component {
constructor(props) {
super(props);
};
editItem = (student) => {
this.props.navigation.navigate('AllStudents');
}
deleteItem = (student) => {
Alert.alert(
'',
'Delete student?',
[
{
text: 'No',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{
text: 'Yes',
onPress: () => this.deleteTheItem(student)
},
],
{cancelable: false},
);
}
deleteTheItem = (student) => {
alert(student);
}
render() {
return(
<List>
<ListItem avatar>
<Left>
<Thumbnail source={require('../../../img/male_avatar.png')} />
</Left>
<Body>
<Text style={styles.userName}>{this.props.surname} {this.props.firstname} {this.props.middlename} </Text>
<Text>{this.props.matric} {this.props.level}L {this.props.phone}</Text>
</Body>
<Right>
<OptionsMenu
customButton={myIcon}
options={["Edit", "Delete"]}
actions={[this.editItem.bind(this,this.props.id), this.deleteItem.bind(this,this.props.id)]}/>
</Right>
</ListItem>
</List>
);
}
}
I have been stucked in this for hours and I have tried all the other links I saw on this issue, but all to no avail.
I will be glad if you can be of help.
Thanks.

You should wrap your component with the HOC withNavigation then the prop will be available in the component, try something like this:
import { withNavigation } from 'react-navigation';
class TheStudent extends Component {
....
}
export withNavigation(TheStudent)

This is one solution which #Rachid Rhafour mentioned in his answer.
You can export your component withNavigation which can import from react-navigation.
import { withNavigation } from 'react-navigation';
class YourClassName extends Component {
}
export withNavigation(YourClassName)
Another approach is you can make route file by which you can navigate to any component file without any trouble.
example:
if there is two or three component to navigate or from navigate you should maintain that route by route file.
import React from "react";
import { createStackNavigator, createAppContainer } from "react-navigation";
import ScreenOne from "./ScreenOne";
import ScreenTwo from "./ScreenTwo";
const AppNavigator = createStackNavigator({
Home: {
screen: ScreenOne
},
Profile: {
screen: ScreenTwo
}
});
export default createAppContainer(AppNavigator);

Related

Trouble passing down this.props.navigation to child components

I am having a little trouble accessing this.props.navigation.navigate in child pages within ViewPager. I have a page where there's a button called "Details" and upon clicking the button it should open up a new separate view (like a new Intent Activity).
Structure is:
Login page -> tap on "login" button -> opens MainPage having a custom CustomBottomNavigationBar with ViewPager component which takes {Object} of 5 different pages and renders them like:
In the root App.js I've already defined this configuration:
// App.js
import MainPage from './views/mainpage';
import PageOne from './views/pageoneview';
import PageTwo from './views/pagetwoview';
import PageOneDetailView from './views/PageOneDetailView';
const MainNavigator = createStackNavigator({
Home: {screen: MainPage},
PageOne: {screen: PageOne},
PageTwo: {screen: PageTwo},
PageOneDetailView: {screen: PageOneDetailView}
},
{
headerMode: 'none',
navigationOptions: {
headerVisible: false,
}
});
// mainpage.js
import React, { Component } from 'react';
import {
StyleSheet,
Image,
View,
TouchableOpacity,
ToastAndroid
} from 'react-native';
import PageOne from './homepages/pageoneview';
import PageTwo from './homepages/pagetwoview';
import CustomBottomNavigationBar from './../components/CustomBottomNavigationBar';
export default MainPage extends Component {
constructor(props) {
super(props);
}
screens = () => {
return {
p1: {page: <PageOne/>},
p2: {page: <PageTwo/>}
}
}
render() {
return (
<CustomBottomNavigationBar
screensets={this.screens()}
/>
);
}
}
Now in PageOne.js there is a button called "Details" and on tapping, it must open a new PageOneDetail.js
// pageoneview.js
import React, { Component } from 'react';
import {
StyleSheet,
Image,
View,
TouchableOpacity,
ToastAndroid
} from 'react-native';
import PageOneDetail from './homepages/PageOneDetailView';
export default PageOne extends Component {
constructor(props) {
super(props);
}
OpenView = (navigateObject, whichScreen) => {
navigateObject(whichScreen);
}
render() {
const {navigate} = this.props.navigation;
return (
<View style={{ flex: 1, alignSelf: 'flex-end' }}>
<TouchableOpacity onPress={() => this.OpenView(navigate, 'PageOneDetailView')}>
<Text> Details </Text>
</TouchableOpacity>
</View>
);
}
}
The error I get when I land on the MainPage is: undefined is not an object this.props.navigation.navigate when mainpage.js tries to load pageoneview.js
Please help me understanding how to fix this issue which I have been facing whole day.
Thanks.
The navigation prop is only accessible to screens, not children of those screens. You can pass down the navigation from the parent or use withNavigation HOC or useNavigation hook from react-navigation-hooks to access it everywhere.

Navigator Trouble

Good afternoon, actually i m keeping error while try to navigate.
This is my App.js
import { createStackNavigator, createAppContainer } from "react-navigation";
import Login from './src/Login';
import NuovoAccount from './src/NuovoAccount';
import HomePage from './src/HomePage';
import Lista_Sveglie from './src/Lista_Sveglie';
import NuovoAccount_2 from './src/NuovoAccount_2';
import Nuova_sveglia from './src/Nuova_sveglia';
import ScreenSveglia from './src/ScreenSveglia';
import Registra from './src/Registra';
import temp from './src/temp';
import Account from './src/Menu/Account';
import ElencoUtenti from './src/Menu/ElencoUtenti';
import MenuImpostazioni from './src/Menu/MenuImpostazioni';
import SelUtenteDest from './src/Menu/SelUtenteDest'
import Accedi from './src/Accedi'
import Landing from './Landing'
const AppNavigator = createStackNavigator(
{
Home: Landing,
Accedi : Accedi ,
Login: Login,
NuovoAccount: NuovoAccount,
HomePage: HomePage,
Lista_Sveglie: Lista_Sveglie,
NuovoAccount_2: NuovoAccount_2,
Nuova_sveglia: Nuova_sveglia,
ScreenSveglia: ScreenSveglia,
Registra: Registra,
temp: temp,
MenuImpostazioni: MenuImpostazioni,
ElencoUtenti: ElencoUtenti,
Account: Account,
SelUtenteDest: SelUtenteDest,
},
{
initialRouteName: "Home",
defaultNavigationOptions: {
headerTintColor: '#ccc',
headerStyle: {
borderBottomWidth: 4,
borderBottomColor: '#80ba27',
backgroundColor: '#364054',
},
headerTitleStyle: {
textAlign: 'center',
flex: 1
},
}
}
);
export default createAppContainer(AppNavigator)
and here my Landing.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, Alert, Button } from 'react-native';
import * as firebase from 'firebase';
import HomePage from './src/HomePage';
import Accedi from './src/Accedi'
import { createStackNavigator, createAppContainer } from "react-navigation";
export default class Landing extends Component {
constructor() {
super();
this.state = {
loggedIn: false,
}
}
componentWillMount() {
console.log("QUI ENTRA")
---some firebase config ...
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.setState({ loggedIn: true })
} else {
this.setState({ loggedIn: false })
}
})
}
render(){
if (this.state.loggedIn){
return <HomePage/>
}else{
return <Accedi/>
}
}
}
Here my HomePage
<View>
<Text
onPress={() => this.props.navigation.navigate('MenuImpostazioni')}
style={style.footer_text_icone}>Configura Impostazioni</Text>
</View>
Can anyone tell me how to fix it and explain why this error ?
from documentation i saw this.props. is created on createnavigator function
"undefined is not an object - this.prop.navigation.navigate"
The problem here is that your HomePage component isn't a direct child of your stackNavigator. You need to pass it trough props to your child component doing:
render(){
if (this.state.loggedIn){
return <HomePage navigation={this.props.navigation}/>
}else{
return <Accedi/>
}
}
Inside the render function of your Landing.js
Then your child component will have access to it.
This is happening because you are using the same component, both as screen that as child component.
{
Home: Landing, //Here (as child)
Accedi : Accedi ,
Login: Login,
NuovoAccount: NuovoAccount,
HomePage: HomePage, //Here
Lista_Sveglie: Lista_Sveglie,
NuovoAccount_2: NuovoAccount_2,
Nuova_sveglia: Nuova_sveglia,
ScreenSveglia: ScreenSveglia,
Registra: Registra,
temp: temp,
MenuImpostazioni: MenuImpostazioni,
ElencoUtenti: ElencoUtenti,
Account: Account,
SelUtenteDest: SelUtenteDest,
}
react-navigation doesn't give access to navigation to a component just because it has been declared inside of it. By doing that if/else you are actually creating a whole new instance of that same component, with the only difference that it do not have access to this.props.navigation.
Landing.js isn't a screen that is defined within your stack navigator, so it does not have access to this.props.navigation.
If you don't want Landing.js within the stack navigator, you can follow this tutorial to use navigate and other navigation actions from any component: https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html

undefined is not a function (evaluating 'navigation.dispatch')

I am trying to navigate to the first page after user logout!
and getting this error:
undefined is not a function (evaluating 'navigation.dispatch').
my action creator code is as follows:
import {NavigationActions} from 'react-navigation';
import {AsyncStorage} from 'react-native';
import {applyMiddleware as dispatch} from "redux";
export const userRemove = (navigation) => {
AsyncStorage.removeItem('user');
const navigateAction = NavigationActions.navigate({
routeName: 'First',
props: {}
});
navigation.dispatch(navigateAction);
};
I have called this action from sideBar of component. The component code is correct since that AsyncStorage.removeItem('user') is working correctly!
sorry for bad grammar. I can't write in english better than this error message here
my component code here:
import React, {Component} from 'react';
import {
Container,
Content,
Footer,
FooterTab,
Button,
Icon
} from 'native-base';
import {userRemove} from '../actions/sideBarAction';
import {connect} from "react-redux";
import {bindActionCreators} from "redux";
class SideBar extends Component {
constructor(props) {
super(props);
}
logout() {
userRemove(this.props.navigation);
}
render() {
return (
<Container>
<Content>
...
</Content>
<Footer>
<FooterTab>
<Button onPress={this.logout.bind(this)}>
<Icon name="logout"/>
</Button>
</FooterTab>
</Footer>
</Container>
)
}
}
const mapStateToProps = state => {
return {
username: state.home.username,
password: state.home.password,
score: state.home.score,
}
};
const mapDispatchToProps = dispatch => {
return Object.assign({dispatch: dispatch},
bindActionCreators(userRemove, dispatch));
};
connect(mapStateToProps, mapDispatchToProps)(SideBar);
Is your component added to you main navigator? If not see if you can add.
You can also wrap your component with withNavigation function from react-navigation. That will make sure you have valid navigation prop.
import { withNavigation } from react-navigation;
...
connect(mapStateToProps, mapDispatchToProps)(withNavigation(SideBar));
Alternatively, you may pass this.props.navigation from parent component too.

Passing props to a component using StackNavigator in React Native

import React, {Component} from 'react'
import { StackNavigator } from 'react-navigation'
import {connect} from 'react-redux'
import {getAllUsers} from '../actions'
import {List, ListItem} from 'react-native-elements'
import { StyleSheet, Text, View, FlatList } from 'react-native'
const UserDetail = () => {
<View>
<Text>User Detail</Text>
</View>
}
const Home = ({ navigation }) => (
<List>
{typeof users === 'string' &&
<FlatList
data={users}
/>
}
</List>
)
const Stack = StackNavigator({
Home: {
screen: Home
},
UserDetail: {
screen: UserDetail
}
})
class MainScreen extends Component {
componentDidMount(){
this.setState({ users : this.props.getAllUsers() })
}
render() {
const users = typeof this.props.decks === 'string'
? Object.values(JSON.parse(this.props.users)) : ''
return(
<Stack />
)
}
}
function mapStateToProps(users) {
return {
users: users,
}
}
function mapDispatchToProps(dispatch) {
return {
getAllUsers: () => dispatch(getAllUsers()),
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(MainScreen)
I have two questions:
1) I want to pass the users props from MainScreen component to Home component and later on also to UserDetail component. But I could not see any example on that on React Navigation documentation except for ScreenProps.
2) If I go to UserDetail and let's say it would be a separate component. And let's say it would call another component. How could it go back to Home for example?
I'm using Redux by the way also here and there are some who suggest to do it in Redux but still I could not make it work also. I am fairly new to React Native or React for that matter, but I could not find a definitive answer so far on this above questions.

undefined is not an object this.props

I try to use navigation between screen in my RN app. This is my code :
INDEX.ANDROID.JS :
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View ,
Button
} from 'react-native';
import {StackNavigator} from 'react-navigation';
import Login from './app/components/Todo';
const SimpleApp = StackNavigator({
Login: { screen: Todo },
});
export default class aap extends Component {
static navigationOptions = { title: 'Welcome', };
render() {
const { navigate } = this.props.navigation;
return (
<Button onPress ={() => navigate('Todo') } title="go"/>
);
}
}
AppRegistry.registerComponent('aap', () => aap);
here is the code of the second screen TODO.JS
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View ,
Button
} from 'react-native';
export default class Todo extends Component {
render() {
return (
<View>
<Text>
Here is my text
</Text>
</View>
);
}
}
When running my code i get an error : undefined is not an object this.props.naviagtion.
Any help is appreciated
You are not using StackNavigator correctly.
Like #xght said, you should be registering SimpleApp instead of aap. Also, you should be using aap as the initial route to your StackNavigator SimpleApp.
This should look something like this:
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View ,
Button
} from 'react-native';
import {StackNavigator} from 'react-navigation';
import Todo from './app/components/Todo';
class aap extends Component {
static navigationOptions = { title: 'Welcome', };
render() {
const { navigate } = this.props.navigation;
return (
<Button onPress ={() => navigate('Todo') } title="go"/>
);
}
}
const SimpleApp = StackNavigator({
Login: { screen: aap },
Todo: { screen: Todo },
});
AppRegistry.registerComponent('aap', () => SimpleApp);
You registered the wrong component, so the navigator SimpleApp doesn't pass the navigation prop to your component.
Replace
AppRegistry.registerComponent('aap', () => aap); by:
AppRegistry.registerComponent('aap', () => SimpleApp);
And also you forgot to add your aap component in SimpleApp routes. And your import Login from './app/components/Todo';is wrong: Login is the name of the route in SimpleApp, and Todo is the name of the component, so you need to replace it by import Todo...