alyn000r alyn000r -4 years ago 446
Javascript Question

React Native how to pass this.setState change to parent

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

Answer Source

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} 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>
    ) 
  }
})
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download