user6726798 user6726798 - 3 months ago 8
React JSX Question

Fetching data from AWS SQS and wait to render ReactJs

So we are having an issues where we send a request to SQS and then on the receive message it returns no data.

To try and fix this we threw in a while loop to poll for an extended period of time; however that really doesn't work because we cannot sleep between polls and it seems as if they are all happening asynchronously.

I say that because if the value does get returned (happens about 50% of the time) it will re render the next screen as many time as cap is left and polling never gets set to false. Could someone please help us out!

render() {
return (
<Navigator
renderScene={this.renderScene.bind(this)}
navigator={this.props.navigator}
navigationBar={
<Navigator.NavigationBar style={{backgroundColor: 'transparent'}}
routeMapper={NavigationBarRouteMapper} />
} />
);
}

renderScene() {
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" hidden={true}/>
<View style={styles.topContainer}>
<View style={styles.bannerContainer}>
<View style={{flexDirection: 'column', flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Image style={styles.mark} source={require('./yb.png')} />
</View>
</View>
<View style={styles.credentialContainer}>
<View style={styles.inputContainer}>
<Icon style={styles.inputPassword} name="person" size={28} color="#FFCD00" />
<View style={{flexDirection: 'row', flex: 1, marginLeft: 2, marginRight: 2, borderBottomColor: '#e0e0e0', borderBottomWidth: 2}}>
<TextInput
style={styles.input}
placeholder="Username"
autoCorrect={false}
placeholderTextColor="#e0e0e0"
onChangeText={(text) => this.setState({username: text})}
value={this.state.username}>
</TextInput>
</View>
</View>

<View style={styles.inputContainer}>
<Icon style={styles.inputPassword} name="lock" size={28} color="#FFCD00" />
<View style={{flexDirection: 'row', flex: 1, marginLeft: 2, marginRight: 2, borderBottomColor: '#e0e0e0', borderBottomWidth: 2}}>
<TextInput
style={styles.input}
placeholder="Password"
autoCorrect={false}
secureTextEntry={true}
placeholderTextColor="#e0e0e0"
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}>
</TextInput>
</View>
</View>
<TouchableOpacity style={styles.forgotContainer}>
<Text style={{color: '#e0e0e0'}}>Forgot Password</Text>
</TouchableOpacity>
</View>
</View>

<TouchableHighlight
underlayColor="#D6AB00"
onPress={this.login}
style={styles.signInButtonContainer}>
<Text style={styles.signInText}>Sign In</Text>
</TouchableHighlight>
</View>
);
}

login() {
var polling = true;
if(this.state.username.length == 0){
Alert.alert("Error","No email entered");
}
else if(this.state.password.length == 0){
Alert.alert("Error","No password entered");
}
else
{
info.username = this.state.username;
info.password = this.state.password;

AWS.sendMessage('****',JSON.stringify(info), (error,result) =>{
if(error != null) console.log("Error Occured Attempting to Send A Message")
else {
var cap=0;
while(cap <= 30 && polling){
cap = cap+1;

AWS.receiveMessages('****'+info.username, (error, result) =>{
if(error != null) console.log("Error");
else{
if(result){
try{
polling = false;
if(result[0] == "[]")
{
console.log(result[0]);
console.log(typeof result[0]);
Alert.alert("Error","Username/Password Incorrect");
}
else
{
console.log(result[0]);
console.log(typeof result[0]);
var temp = JSON.parse(result[0]);
this.props.navigator.replace({
id: 'MapIOS',
data: {
username: info.username,
ofAge: temp[0].ofAge,
uid: temp[0].u_ID
},
});
}
}
catch(e){
console.log(e);
}
}
AWS.deleteMessage('***'+info.username, result[1], (error) => {
if(error != null) console.log("Error");
});
}
});
}
return
}
});
}
}
};

Answer

The problem is that you are calling AWS.ReceiveMessage in a loop.

When you call AWS.ReceiveMessage, the call is asynchronous. Meaning, it will return immediately. It does not wait for your callback to be called. So your loop can be exhausted before any of the callbacks get called.

Trying to set your polling variable from your callback function is not a safe way to "protect" your callback.

You need to restructure your function so that the second AWS.ReceiveMessage does not happen until after your callback has been called from the first AWS.ReceiveMessage.

Generally speaking, don't loop.