React Native中比较运算符未按预期工作问题排查
React Native中n-back功能状态比较异常的问题解决
问题背景
我正在开发一个类n-back功能的应用:随机在某个盒子中显示文本,之后再次随机显示文本,并提示用户当前盒子是否与上一个(或设定步数前的)盒子相同。通过数组存储盒子序列,将当前盒子存入数组索引0,与索引1的上一个盒子比较。该逻辑在Vanilla JavaScript中运行正常,但在React Native中出现异常,推测问题源于checkPrevious函数的比较操作。
问题根源
React的useState状态更新是异步批量执行的,这是和Vanilla JS同步修改数据的核心区别:在start函数中调用setBoxesArr后立刻执行checkPrevious,此时boxesArr还未完成更新,拿到的仍是更新前的旧数组状态,自然无法正确比较当前和上一个盒子的数值。
解决方案
方案一:用useEffect监听数组变化
通过useEffect钩子监听boxesArr的变化,当数组长度达到2及以上时再执行比较逻辑,确保拿到最新的数组状态:
import React, { useState, useEffect } 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) // 监听数组变化,执行比较逻辑 useEffect(() => { if (boxesArr.length >= 2) { setSame(boxesArr[0] === boxesArr[1] ? "Yes" : "No"); setTimeout(clearBox, 1000); } }, [boxesArr]); function start() { setHasStarted(true) let num = Math.floor(Math.random() * 3) + 1; setBox(num) setBoxesArr((prev) => { return [num, ...prev] }) } function clearBox() { setBox(0) setTimeout(start, 500) } // 以下render部分与原代码一致 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" } });
方案二:在setBoxesArr回调中直接处理比较
如果不想使用useEffect,可以在更新数组的回调函数中直接拿到最新数组,完成比较逻辑:
function start() { setHasStarted(true) let num = Math.floor(Math.random() * 3) + 1; setBox(num) setBoxesArr((prev) => { const newArr = [num, ...prev]; // 新数组长度满足条件时直接比较 if (newArr.length >= 2) { setSame(newArr[0] === newArr[1] ? "Yes" : "No"); setTimeout(clearBox, 1000); } return newArr; }) }
内容的提问来源于stack exchange,提问作者DingleberrySmith
相关产品推荐
相关产品推荐

