undefined is not an object (evaluating 'this.props.dispatch') - react-native

i have this React native component that contains two classes the first has a button that i want it to redirect me to another page it doesn't redirect anything it's just dispatching error . When i try the same function of redirection with the second class it works . Where is the problem please ?
import React, { Component } from 'react';
import {
TouchableOpacity ,
View,
BackHandler,
Image,
Text,
Button,
Platform,
ActivityIndicator
} from 'react-native';
import {connect } from 'react-redux'
class HeaderBarWebView extends Component{
constructor(props){
super(props);
}
goCamera(){
this.props.dispatch(changeCurrentPage("camera"))
}
render(){
return(
<View>
<TouchableOpacity style={{justifyContent:'center',display: 'flex'}}
onPress={this.goCamera}>
<Image
style={{tintColor:"white" , height:30,
width:30,marginRight:20}}
source={require('../resource/img/camera.png')}
/>
</TouchableOpacity>
</View>
)}}
class WebviewApp extends Component{
constructor(props)
{
this.state={}
this.goCamera= this.goCamera.bind(this)
goCamera(){
this.props.dispatch(changeCurrentPage("camera"))
}
render()
{
return(
<View style={{flex:1,width:"100%"}}>
<Button title="Press me" onPress={this.goCamera}></Button>
<CustomWebView
...........................
/>
</View>
);
}
}
const mapStateToProps = state => ({
page:state.router.page,
camera : state.router.camera
})
const WebviewAp = connect(mapStateToProps)(WebviewApp,HeaderBarWebView)
export default WebviewAp
Here is the error shown

You need to bind goCamera function with "this", in constructor;
constructor(props){
super(props);
this.goCamera = this.goCamera.bind(this);
}

Related

React Native: Updating the state from child to parent and then pass updated props at second component

I am trying to change the value of props at second Recipe-Component updating the state.
I tried to use timer, alerts. but I had also problem.
App js:
import React, { Component } from "react";
import Recipe from "./Recipe";
import {Text, View } from "react-native";
export default class App extends Component {
constructor() {
super();
this.state = {
name: "Pancaces",
isYummy: true
};
}
update = (s) => {
this.setState({name : s.name, isYummy: s.isYummy });
}
render() {
return (
<View style={{alignItems: 'center'}}>
<Recipe update={this.update} name={this.state.name} isYummy={this.state.isYummy} delay={false}/>
<Text>{this.state.name}</Text>
<Recipe name={this.state.name} isYummy={this.state.isYummy} delay={true}/>
</View>
);
}
}
Recipe.js
import React, * as react from "react";
import PropTypes from "prop-types";
import { Text, View } from "react-native";
import styles from "./styles.js";
export default class Recipe extends react.Component{
static propTypes = {
name: PropTypes.string.isRequired,
isYummy: PropTypes.bool.isRequired
};
constructor(props){
super(props)
this.state = {
update : this.update,
name : this.props.name,
isYummy: this.props.isYummy
}
if(this.props.update) this.props.update(({name:'Lentils', isYummy:false}))
};
render() {
return (
<View style={styles.container}>
<Text style={styles.text_container} >{this.state.name}</Text>
{this.state.isYummy ? <Text>THIS RECIPE IS YUMMY</Text> : null}
</View>
);
}
}
Current Output is:
Pancakes
THIS RECIPE IS YUMMY
Lentils
Pancakes
THIS RECIPE IS YUMMY
I expect output
Pancakes
THIS RECIPE IS YUMMY
Lentils
Lentils
SOLVED
I believe this is happening because you are trying to display the values from your state instead of your props and since the constructor isn't called a second time after updating, your state doesn't get reassigned. Here's what I would do:
//Recipe.js
constructor (props)
{
super(props);
if (this.props.update)
this.props.update(({name:'Lentils', isYummy:false}));
}
render()
{
return (
<View style={styles.container}>
<Text style={styles.text_container}>
{this.props.name}
</Text>
{this.props.isYummy &&
<Text>
THIS RECIPE IS YUMMY
</Text>
}
</View>
);
}

Call parent function from Child component not working

I have 2 component parent(LoginScreen) and a child(SignupSection). Child component have onClick button. When user click button I need to fire function from the parent component and this is not working for me. I have the following code
I want Call parent function from Child component
Parent
import React, {Component} from 'react';
import Wallpaper from './Wallpaper';
import SignupSection from './SignupSection';
export default class LoginScreen extends Component {
constructor(props) {
super(props)
}
childcall()
{
alert("hello , this call from child component");
}
render() {
return (
<Wallpaper>
<SignupSection
childcall ={this.childcall.bind(this)}
/>
</Wallpaper>
);
}
}
Child
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {StyleSheet, View, Text} from 'react-native';
export default class SignupSection extends Component {
constructor(props) {
super(props)
}
componentWillMount()
{
}
render() {
return (
<View style={styles.container}>
<Text style={styles.text} onClick={()=>this.props.childcall()}>Create Account</Text>
<Text style={styles.text}>Forgot Password?</Text>
</View>
);
}
}
Text does not have onClick. There is only onPress or you should wrap your text component inside TouchableOpacity and then call your callback inside onPress
Fix :
return (
<View style={styles.container}>
<Text style={styles.text} onPress={()=>this.props.childCall()}>Create Account</Text>
<Text style={styles.text}>Forgot Password?</Text>
</View>
);

How to link mapStateToProps to two classes in the same React Native component

I have two classes in my react native component the first es without export so it's just a class the second is with export default. And then have mapStateToProps it's linked to the second class and it works fine but now I want to link the first class also because this.props.dipatch is not working . Have you any solution? Here is my code :
import React, { Component } from 'react';
import {
TouchableOpacity ,
View,
BackHandler,
Image,
Text,
Button,
Platform,
} from 'react-native';
import {connect } from 'react-redux'
class HeaderBarWebView extends Component{
constructor(props){
super(props);
}
goCamera(){
this.props.dispatch(changeCurrentPage("camera"))
}
render(){
return(
<View>
<TouchableOpacity style={{justifyContent:'center',display: 'flex'}}
onPress={this.goCamera}>
<Image
style={{tintColor:"white" , height:30,
width:30,marginRight:20}}
source={require('../resource/img/camera.png')}
/>
</TouchableOpacity>
</View>
)}}
class WebviewApp extends Component{
constructor(props)
{
this.state={}
this.goCamera= this.goCamera.bind(this)
goCamera(){
this.props.dispatch(changeCurrentPage("camera"))
}
render()
{
return(
<View style={{flex:1,width:"100%"}}>
<Button title="Press me" onPress={this.goCamera}></Button>
<CustomWebView
...........................
/>
</View>
);
}
}
const mapStateToProps = state => ({
page:state.router.page,
})
const WebviewAp = connect(mapStateToProps)(WebviewApp)
export default WebviewAp
You can also connect the first class just like second class
connect(mapStateToProps)(HeaderBarWebView);
const WebviewAp = connect(mapStateToProps)(WebviewApp);
export default WebviewAp;
But the batter way you should create new files for all separate component and use with import and export logic.

can not read property navigate of undefined

I am mapping array to component.
{this.state.forms.map((data)=><Box data={data} />)}
and the code for component Box is
import React,{Component} from 'react'
import {View,Text,ScrollView,Image,Button,StyleSheet,AsyncStorage} from 'react-native'
class Login extends Component{
constructor(props){
super(props)
this.state = {
forms:[],
}
this.onSetCompany = this.onSetCompany.bind(this)
}
onSetCompany(data){
console.log(data)
// AsyncStorage.setItem('Company',data);
this.props.navigation.navigate('CompanyDeatails')
}
render(){
return(
<View style={style.container}>
{console.log(this.props.data)}
<View style={style.box}>
<View style={style.box1}>
<Text style={style.row2}>{this.props.data.CompanyName} bkb</Text>
</View>
<View style={style.box3}>
<Text style={style.row2}>{this.props.data.LastDate} </Text>
</View>
</View>
<View style={style.buttonBox}>
<View style={style.button}>
<Button color="#6d5d17" title="Fill" onPress={()=>this.props.navigation.navigate('CompanyDeatails')}></Button>
</View>
</View>
</View>
)
}
}
export default Login
var style = StyleSheet.create({
.....
})
and my Routes
export default class App extends Component{
render(){
return(
<Links />
)
}
}
const Links = DrawerNavigator({.....,
CompanyDeatails:{screen:CompanyDeatails},
....,
},{contentComponent:props => <Slider {...props}/>
})
When i Map array to Box then navigation in that box is not working.I have working navigation to which are working on my rest of app but not in this particular component.
Like
in login.js, I have this.props.navigation.navigate('C1')
Which is working but when I paste same line in Box component it throw error.
Can not read property navigate of undefined
If Box component is not part of navigator then, you should wrap it within withNavigation function inorder to access the navigation object. Take a look at the doc here
Consider the following example
import React from 'react';
import { withNavigation } from 'react-navigation';
class Box extends React.Component {
...
render() {
...
}
}
export default withNavigation(Box);
Now, within the Box component, you can access this.props.navigation.navigate function.
Hope this will help!

change view in react native (0.5)

I have 2 views and I want to move from the first one to the second one without using createStackNavigator
There´s no need to use navigation because the first view is just a welcome screen
import React from 'react';
import { View, Text, Button } from 'react-native';
class HomeScreen extends React.Component {
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>Welcome!</Text>
<Button
title="sign In"
onPress={() => navigate('SignInScreen')}
/>
</View>
);
}
}
class SignInScreen extends React.Component {
render() {
return (
<View>
<Text>Sign In screen</Text>
</View>
);
}
}
export default HomeScreen
the error I´m getting is
TypeError: undefined is not an object (evaluating 'this.props.navigation.navigate')
thank you.
Use a flag on state. When you click the button on HomeScreen, it will change the flag to true, which will allow the conditional statement to call the SignInScreen to be rendered.
import React from 'react';
import { View, Text, Button } from 'react-native';
class HomeScreen extends React.Component {
state = {
loggedIn: false,
};
render() {
const { navigate } = this.props.navigation;
return this.loggedIn ? (
<SignInScreen />
) : (
<View>
<Text>Welcome!</Text>
<Button
title="sign In"
onPress={() => this.setState({ loggedIn: true })}
/>
</View>
);
}
}
class SignInScreen extends React.Component {
render() {
return (
<View>
<Text>Sign In screen</Text>
</View>
);
}
}
export default HomeScreen;