I am new to React Native I am making a sample app where the user can login and register for a new account.
I have two React classes,
One is the main class index.ios.js and another class called register.js. In the index class I am saying if the variable register is true render the register screen.
In the class register.js I am trying to set the variable register to false using this.setState({register:false}) but it is not causing the re render of the parent (index.ios.js). Is the a super(state) method or something similar that I am missing ? I believe the parent state is not getting the values of the updated register variable.
Here are my classes:
Render inside index.ios.js:
render: function() {
if(this.state.register) {
return this.renderRegisterScreen();
}
else if (this.state.loggedIn) {
return this.userLoggedIn();
}
else {
return this.renderLoginScreen();
}
}
Register.js:
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TouchableHighlight,
TextInput,
} = React;
var Register = React.createClass({
render: function() {
return (
<View style={styles.container}>
<View style={styles.rafitoImage}>
<Image source={require('./logo.png')}></Image>
<Text style={styles.slogan}>Eliminate the need to wait!</Text>
</View>
<View style={styles.bottomSection}>
<View style={styles.username}>
<View style={styles.inputBorder}>
<TextInput placeholder="Username..." style={styles.usernameInput} onChangeText={(text) => this.setState({username: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput password={true} placeholder="Password..." style={styles.usernameInput} onChangeText={(text) => this.setState({password: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput password={true} placeholder="Verify Password..." style={styles.usernameInput} onChangeText={(text) => this.setState({verifyPassword: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput placeholder="Phone.." style={styles.usernameInput} onChangeText={(text) => this.setState({phone: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput placeholder="Email.." style={styles.usernameInput} onChangeText={(text) => this.setState({email: text})}/>
</View>
<TouchableHighlight style={styles.button}
underlayColor='#f1c40f' onPress={this.register}>
<Text style={styles.buttonText}>Register</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.signUp} onPress={this.resetToLogin}
underlayColor='#ffffff'>
<Text style={styles.signUpText}>Already A Member </Text>
</TouchableHighlight>
</View>
</View>
<View style={styles.copyright}>
</View>
</View>
);
},
resetToLogin: function() {
this.setState({
register: false //I want this to re render the home screen with the variable register as false
});
}
});
var styles = StyleSheet.create({
container: {
flex : 1
},
bottomSection: {
flex: 5,
flexDirection: 'row'
},
button: {
height: 36,
backgroundColor: '#32c5d2',
justifyContent: 'center',
marginTop: 20
},
buttonText: {
fontSize: 18,
color: 'white',
alignSelf: 'center'
},
signUpText: {
color: '#3598dc'
},
signUp: {
alignItems: 'flex-end',
marginTop: 10,
},
username: {
flex: 1,
padding: 5
},
rafitoImage: {
flex: 3,
justifyContent: 'center',
alignItems: 'center',
},
copyright: {
alignItems: 'center'
},
usernameInput: {
height: 36,
marginTop: 10,
marginBottom: 10,
fontSize: 18,
padding: 5
},
copyrightText: {
color: '#cccccc',
fontSize: 12
},
inputBorder: {
borderBottomWidth: 1,
borderBottomColor: '#ececec'
},
slogan: {
color: '#3598dc'
}
});
module.exports = Register;
Attempt 1
As per the answer I added this to my index.ios.js
renderRegisterScreen: function() {
return (
<Register login={this.login}/>
)
}
And I added this to my register.js
<TouchableHighlight style={styles.signUp} onPress={this.props.login}
underlayColor='#ffffff'>
<Text style={styles.signUpText}>Already A Member </Text>
</TouchableHighlight>
But for some reason it does not even go to the register screen anymore, it executes the login function as soon as the register screen renders. What am I missing now ? Please advise.
Thanks
Update
It works when I pass down registered as a property but not when I do not. I would like to understand why if someone could post that.
Thanks
You can pass the function down to the child as props, then set the state of the parent from within the child that way.
Parent Component:
var Parent = React.createClass({ getInitialState() { return { registered: false } }, register(){ console.log("logging in... "); this.setState({ registered: true }); }, render: function() { return ( <View style={styles.container}> <Child register={this.register.bind(this)} registered={this.state.registered} /> {this.state.registered && <View style={{padding:10, backgroundColor:'white', marginTop:10}}> <Text style={{fontSize:20}}>Congratulations, you are now registered!</Text> </View>} </View> ); } });
Child Component:
var Child = React.createClass({ render: function() { return( <View style={{backgroundColor: 'red', paddingBottom:20, paddingTop:20 }}> <TouchableHighlight style={{padding:20, color: 'white', backgroundColor: 'black'}} onPress={() => this.props.register() }> {this.props.registered ? <Text style={{color: 'white'}}>registered</Text> : <Text style={{color: 'white'}}>register</Text>} </TouchableHighlight> </View> ) } })
Here is a more powerful solution. This will let the child component change any state variable in the parent.
Parent component:
render: function() { return ( ... <Child setParentState={newState=>this.setState(newState)} /> ... ); }
// Take note of the setState()
Child component:
this.props.setParentState({registered: true})
Why my attempt was failing was because I was using
onPress={this.props.login}
It should be
onPress={()=>this.props.login}
because of that mistake my onPress function would execute as soon as the button would render. I am not sure why that happens but I know what my mistake was.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With