Call parent function from Child component not working - react-native

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>
);

Related

How to re-render import component on state change

I have made two component (parent & child) & import the child component containing react-native modal
I have render child component after state change, it renders first time but on second time, it doesn't work.
Parent.js file is as follows:
import react, {Component} from 'react';
import { View, Text, TouchableOpacity} from 'react-native';
import ActionModal from './ActionModal';
export default class Parent extends Component {
constructor(props){
super(props);
this.state = { tabclicked: false }
}
actiontabclicked = () => {
this.setState({ tabclicked: true });
}
render(){
return (
<View>
<TouchableOpacity onPress={() => { this.actiontabclicked()} }>
<Text> MOVE</Text>
</TouchableOpacity>
{ (this.state.tabclicked) ? <ActionModal /> : null }
</View>
)
}
}
ActionModal.js file code
import React, {Component} from 'react';
import {Modal, Text, TouchableHighlight, View, Alert} from 'react-native';
export default class ActionModal extends Component {
constructor(){
super();
this.state = { modalVisible: true }
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
render() {
return (
<View style={{marginTop: 22}}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { this.setModalVisible(!this.state.modalVisible)}}>
<View style={{marginTop: 22}}>
<View>
<Text>Hello World!</Text>
</View>
</View>
</Modal>
</View>
);
}
}
ActionModal opens first time but not second time, I think this is because state becomes true but after close modal it doesn't reset.
How can I achieve that ? Thanks in advance
You're not being so clear with what you want to achieve, if you want to achieve this behaviour of tapping > dismiss > tap again > shows
you should make something like this on your setModalVisible function:
setModalState = () => {
this.setState(prevState => ({
modalVisible: !prevState.modalVisible
})
}
This will change the state opposite to what it was. If you want to have more control maybe you can create two functions setModalOpen and setModalClosed
Maybe you can use props on the child component when onRequestClose is triggered to pass this function to the parent and there you can call setModalClosed, the way you have to do it is to make a callback with the given props (look for passing props to parent in react on the internet, it's quite simple)
Hope I could help

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>
);
}

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.

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

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);
}

NavigatorIOS problems

Hi I'm having some trouble using the NavigatorIOS in my app, it gives me the error:'undefined is not an object(evaluating 'this.props.navigator.push').
I tried to see some examples but I can't see the error, can someone help me?
Here is the code:
import React, { Component, PropTypes } from 'react';
import Dimensions from 'Dimensions';
import Menu from './Menu'
import {
AppRegistry,
StyleSheet,
Image,
TouchableHighlight,
NavigatorIOS,
FadeInView,
Text,
View
} from 'react-native';
class Home extends React.Component {
constructor(props, context) {
super(props, context);
this.onForward = this.onForward.bind(this);
}
onForward(Menu){
this.props.navigator.push({
component: Menu,
title: "Menu",
navigationBarHidden: true,
});
}
render() {
return (
<View style={styles.container}>
<Image
style={styles.img}
source={require('./img/scrittaNera.png')}
onLoadStart={(e) => this.setState({loading: true})}
/>
<TouchableHighlight style={styles.button} onPress={() => this.onForward()}>
<Text style={styles.buttonText}>Get Inspired</Text>
</TouchableHighlight>
</View>
);
}
}
Thanks
You need to bind the function to your Component in this case this can be done as follows:
<TouchableHighlight
style={styles.button}
onPress=this.onForward.bind(this)>
....
</TouchableHighlight>
Also you need to make sure your main component is wrapped inside a <NavigatorIOS> component. Such as:
import React, { Component, PropTypes } from 'react';
import { NavigatorIOS, Text } from 'react-native';
export default class NavigatorIOSApp extends Component {
render() {
return (
<NavigatorIOS
initialRoute={{
component: MyScene,
title: 'My Initial Scene',
}}
style={{flex: 1}}
/>
);
}
}