Reputation: 7
I'm trying out some things in React Native for the first time and i'm trying to roll 3 dices (text based for now).
I'm using a for loop to go over an array of the 3 dices. However i'm only seeing one dice text being updated (the 3rd one).
Also when doing some alerts to check what's going on within that for loop, i'm seeing unexpected things? the first alert says 2, the second alert says 1 and then it usually no longer alerts, seldom it also alerts a third time with a 0.
My code so far:
(file: Game.js)
import React from 'react'
import { StyleSheet, Image, Text, View, Button } from 'react-native'
export default class Home extends React.Component {
state = {
dices: [null, null, null],
rollsLeft: 3,
keepDices: [false, false, false],
}
//When this component is mounted (loaded), do some defaults
componentDidMount() {
}
//Roll dices
rollDices = () => {
for(let i = 0; i < 3; i++){
alert('for loop at ' + i);
//Math random to get random number from rolling the dice
randomNumber = Math.floor(Math.random() * 6) + 1;
//Check if the user wanted to keep a dice's value before reassigning a new value
if(this.state.keepDices[i] === false){
//User want to roll this dice, assign new random number to it
//this.setState.dices[i] = randomNumber;
let newDices = [ ...this.state.dices ];
newDices[i] = randomNumber;
this.setState({ dices : newDices });
}
}
//Deduct 1 roll from total
this.setState.rollsLeft--;
//TODO: Check if rolls equals 0, then make player2 active!
}
render() {
return (
<View style={styles.container}>
<Text> {this.state.dices[0]} ONE </Text>
<Text> {this.state.dices[1]} TWO</Text>
<Text> {this.state.dices[2]} THREE</Text>
<Text>Turns left: {this.state.rollsLeft} </Text>
<Button
title="Roll 🎲"
onPress={this.rollDices} />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
},
})
Upvotes: 0
Views: 229
Reputation: 7
Together with DCQ's valuable input for async setStates bundling I also noticed that i'm always resetting the copied dice array within the for loop and thus only saving my last dice correctly.
Next up the for loop was actually counting right from 0 to 2 however the alert boxes don't interrupt the code as i'm used to in the browser therefore it looked a bit off. When doing console.log (which is also cleaner and more correct logging) I noticed things did went right there.
Upvotes: 0
Reputation: 111
In React Native the setState
function is asynchronous.
Meaning that this.setState({ dices : newDices });
can end up setting dices to different values depending on which finishes first.
If you want to control what happens after you use setState, you can call a function after the set is done like this
this.setState({dices: newDices}, () => {
// Do something here.
});
There is some really useful information on calling function after the setState here: Why is setState in reactjs Async instead of Sync?
and some good explanations of how setState in react works and how to get around it here: https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3
Upvotes: 3