undefined is not an object (evaluating 'this.props.navigation') react navigation - reactjs

I'm using React Stack Navigator in React Native App. I have a problem with the navigation props.
Here is my component where I call my navigate method.
class CommandsList extends React.Component {
constructor(props){
super(props);
}
addCommand(){
this.props.navigation.navigate("CreateCommand");
}
render() {
return (
<SafeAreaView style={{flex:1}}>
<MyList itemsUrl="http://localhost:9000/commands"/>
<Button title="Ajouter" onPress={this.addCommand}></Button>
</SafeAreaView>
);
}
}
export default StackNavigator({
CommandsList : {
screen : CommandsList,
},
});
And my App.js
const RootStack = StackNavigator(
{
CommandsList: {
screen: CommandsList,
},
CreateCommand: {
screen: CreateCommand,
}
},
{
initialRouteName: 'CommandsList'
}
);
export default class App extends React.Component {
render() {
return <RootStack/>;
}
}
I don't understand why I have an error on navigate methods. :/

You need to bind your reference either using bind in the constructor or by using the fat arrow function to reference this to the context
addCommand = () => {
this.props.navigation.navigate("CreateCommand");
}
or
constructor() {
super()
this.addCommand = this.addCommand.bind(this);
}
Also you may check this article

Related

react-navigation navigate is not a function error. - Class component

I'm using react native class component and I'm using react-navigation to route in the app. the guide is mostly for the functional component and I'm trying to implement it with class components. but when i trying to get it from reactnavigation it always throws me error that navigation is not a function or undefined. Im sorry if this is an already asked question as I'm really new to this react native.
class component
import React from 'react';
import { useNavigation } from '#react-navigation/native';
import { Button, Divider, Layout, TopNavigation ,Card,Text} from '#ui-kitten/components';
class HomeScreen extends React.Component {
navigateDetails(navigation) {
debugger
navigation('Details');
};
constructor(props) {
super(props);
console.log(this.props);
this.state = { hover: false };
}
render() {
const navigation = this.props;
return(
<Button onPress={this.navigateDetails}>OPEN DETAILS</Button>
);
}
}
export default function (props) {
const navigation = useNavigation();
return <HomeScreen {...props} navigation={navigation} />;
}
First, you have to make sure navigation prop is exist in your class component (As looking in your code its already exist) and the second thing is this.props.navigation is an object, not a function which holds different function like navigate, push etc so you have to execute these functions, here are some changes I did in your code and I hope this will work for you.
class HomeScreen extends React.Component {
constructor(props) {
super(props);
console.log(this.props);
this.state = { hover: false };
}
navigateDetails() {
this.props.navigation.navigate('Details');
};
render() {
const navigation = this.props;
return(
<Button onPress={()=>this.navigateDetails()}>OPEN DETAILS</Button>
);
}
}
export default function (props) {
const navigation = useNavigation();
return <HomeScreen {...props} navigation={navigation} />;
}
Seems I have to pass that navigation to the function as a variable in order to work. so I have changed the function as bellow to pass the navigation to the
function and also changed this.navigateDetails(navigation) to
()=>this.navigateDetails(navigation)
also, I destructed the navigation like const {navigation} = this.props;
full code line
onPress={()=>this.navigateDetails(navigation)}

Not able to pass a function as a prop to child in my react native app

I have my main App.js where i am only doing some routing and settings states in the constructor and looks like this.
class App extends React.Component {
constructor() {
super()
this.state= {
modalstuffshown: false,
modalitems: null,
}
this.newalerter = this.newalerter.bind(this);
}
newalerter() {
Alert.alert("hey")
}
const MainScreenPage = () => (
<View>
<TopMovies />
</View>
)
const SearchPage = () => (
<View>
<SearchPageComp
newalerter={this.newalerter}
/>
</View>
)
export const RootTabs = TabNavigator({
MSPage: {
screen: MainScreenPage,
},
SPage: {
screen: SearchPage,
},
})
export default RootTabs;
And I am trying to call the function newalerter which should alert with "hey" inside my SearchPageComp after passing it as props gives an error.
<Button onPress={()=>{this.props.newalerter()}} title="click here" />
But i get an error saying undefined is not a function (evaluating '_this3.props.newalerter()')
Is it because I am not exporting App class as default by doing
export default class RandomShakePage extends React.Component {
I am already exporting the RootTabs as default and it says I can only export one per module.

Export functions out of react native components

I just want to export a function to an actions.js file but i cannot get to work.
This is the working base:
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
visible: false
}
}
onOpen = () => {
this.setState({visible:true});
console.log(this.state.visible);
}
render() {
return (
<View style={styles.container}>
<Button onPress={()=>{this.onOpen();}}>More</Button>
</View>
);
}
}
And now i tried this, which gives me an error when i press the button:
Error:
Unhandled JS Exception: _this.setState is not a function. (In '_this.setState({ visible: true })', '_this.setState' is undefined)
Code:
let onOpen = () => {
this.setState({visible:true});
console.log(this.state.visible);
}
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
visible: false
}
this.onOpen = onOpen.bind(this);
}
render() {
return (
<View style={styles.container}>
<Button onPress={()=>{this.onOpen();}}>More</Button>
</View>
);
}
}
You cannot use the 'this' keyword outside the class Component. you cannot change the state of the component from outside the class.
More details here:
Change state Outside Component
Further, If you want to change the state of the component outside a class, make use of redux state.
Redux JS
The problem with your code is that you've define onOpen outside your class and you want to access setState function of the Component. I don't know why one would want to do this because onOpen belongs to class. But still if you want to put this outside class. You can do this by following way:
let onOpen = ({setState}) => {
//retrieve setState here
setState({visible:true});
}
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
visible: false
}
// You don't have to do this if onOpen is not in your class
//this.onOpen = onOpen.bind(this);
}
render() {
//send this.setState to onOpen
const that = this;
return (
<View style={styles.container}>
<Button onPress={()=>{onOpen({setState: that.setState});}}>More</Button>
</View>
);
}
}

use navigate method anywhere

I have a component that not assign in StackNavigator. However I still want to use navigate method from react-navigation. Is that possible ?
For example:
manage.js
export const mainStack = StackNavigator({
Home: { screen: HomeScreen},
Content: { screen: ContentScreen },
});
OtherContent.js
class OtherContent extends React.Component {
constructor(props) {
super(props);
}
_MoveToScreen = () =>{
//try to open ContentScreen from here
const { navigate } = this.props.navigation;
navigate('ContentScreen');
}
}
I want to use navigate in OtherContent component. How can I pass the navigation props to the component.
Use redux and put it in the state, then u can call it from there i think
You can pass navigation from parent as props or use withNavigation Higher Order Component by react-navigation
Example 1:
<OtherContent navigation={this.props.navigation} />
Example 2:
import React from 'react';
import { withNavigation } from 'react-navigation';
class OtherContent extends React.Component {
constructor(props) {
super(props);
}
_MoveToScreen = () =>{
//try to open ContentScreen from here
const { navigate } = this.props.navigation;
navigate('ContentScreen');
}
// ...
}
const OtherContentWithNavigation = withNavigation(OtherContent);
;

React Native doesn't update child component props

I'm working on a React Native project and I realized that React Native seems to break the React flow (Parent to children) props update.
Basically, I'm calling a "Menu" component from an "App" component, passing a prop to "Menu". However, when I update the "App" state, the props on "Menu" should update, but this doesn't happen. Am I doing something wrong?
That's my code:
App.js
import React from 'react';
import {
View,
Text
} from 'react-native';
import Menu from './Menu';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
opacity: 2
}
}
componentDidMount() {
setTimeout(() => {
this.setState({
opacity: 4
});
}, 3000);
}
render() {
return(
<View>
<Menu propOpacity={this.state.opacity} />
</View>
);
}
}
export default App;
Menu.js
import React from 'react';
import {
View,
Text
} from 'react-native';
class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {
menuOpacity: props.propOpacity
}
}
render() {
return(
<View>
<Text>Menu opacity: {this.state.menuOpacity}</Text>
</View>
);
}
}
Menu.propTypes = {
propOpacity: React.PropTypes.number
}
Menu.defaultProps = {
propOpacity: 1
}
export default Menu;
React is not breaking data flow... You are. After initial state initialisation, you forget to update Menu's state later, when parent sends updated props.
Try this...
class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {
menuOpacity: props.propOpacity
}
}
componentWillUpdate(nextProps, nextState) {
nextState.menuOpacity = nextProps.propOpacity;
}
render() {
return(
<View>
<Text>Menu opacity: {this.state.menuOpacity}</Text>
</View>
);
}
}

Resources