You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:35:38