I am trying to create something that requires a sort of n-back functionality. Here I have recreated something similar with text showing in a random box, and then again showing in a random box, and it is supposed to tell you if it was the same as the previous box (or the same as however many boxes ago you have it set to).
I am using an array and comparing the current box I have pushed to the 0th index in the array with the previous box (the 1 index).
This works fine for me in vanilla Javascript. But in React Native, I don't really understand what is happening.
https://snack.expo.dev/@skjones90/58123f
import React, { useState } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
const [box, setBox] = useState(0)
const [same, setSame] = useState("")
const [boxesArr, setBoxesArr] = useState([])
const [hasStarted, setHasStarted] = useState(false)
function start() {
setHasStarted(true)
let num = Math.floor(Math.random() * (3 - 1 1) ) 1;
setBox(num)
setBoxesArr((prev) => {
return [num, ...prev]
})
checkPrevious()
}
function checkPrevious() {
if (boxesArr[0] === boxesArr[1]) {
setSame("Yes")
} else {
setSame("No")
}
setTimeout(clearBox, 1000)
}
function clearBox() {
setBox(0)
setTimeout(start, 500)
}
return (
<View style={styles.container}>
<Text>Same as previous? {same}</Text>
<View style={styles.boxes}>
<View style={{
width: 100,
height: 100,
backgroundColor: "blue"
}}>
<Text style={styles.paragraph}>
{box === 1 ? "Here" : null}
</Text>
</View>
<View style={{
width: 100,
height: 100,
backgroundColor: "red"
}}>
<Text style={styles.paragraph}>
{box === 2 ? "Here" : null}
</Text>
</View>
<View style={{
width: 100,
height: 100,
backgroundColor: "orange"
}}>
<Text style={styles.paragraph}>
{box === 3 ? "Here" : null}
</Text>
</View>
</View>
<TouchableOpacity onPress={() => {hasStarted === false ? start() : null}}>
<View style={{backgroundColor: "purple", width: 100, marginTop: 10}}>
<Text style={{textAlign: "center", color: "white"}}>
Start
</Text>
</View>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: "center",
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
paddingLeft: 8,
paddingRight: 8,
paddingTop: 10
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
boxes: {
flexDirection: "row"
}
});
I assume the problem stems from the comparison made in the "checkPrevious" function.
CodePudding user response:
Your problem is that the following:
setBoxesArr((prev) => {
return [num, ...prev]
});
doesn't change your boxesArr
immediately. It is only in the next render of your component that boxesArr
will hold the new value that you set. That means that when you call checkPrevious()
, boxesArr
is still the old value and not the one you just set. Since the same
state is derived from your boxesArr
, I would suggest removing the checkPrevious()
function and the same
state and instead calculate it upon the render of your component:
const same = boxesArr[0] === boxesArr[1] ? "Yes" : "No";
See example here.