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

React useState Hook操作数组:点击元素添加索引不生效如何解决

问题原因

你代码有两处核心的事件绑定错误,导致点击事件没有正确触发状态更新:

  1. Game.js 中给RandomNumber传递onClick的写法错误
    你写的是onClick={() => selectNumber},这个箭头函数只是返回了selectNumber函数本身,没有实际执行状态更新逻辑。
  2. RandomNumber.js 中TouchableOpacity的onPress写法错误
    你写的是onPress={handlePress()},相当于组件渲染时就直接执行了handlePress,不是点击时触发。
    另外还有一个逻辑问题:你没有把随机数和目标值缓存,每次状态更新组件重渲染时,所有随机数都会重新生成,游戏逻辑无法正常运行,建议用useMemo包裹随机数和目标值的生成逻辑。

修复后的代码

Game.js

import { StatusBar } from "expo-status-bar";
import React, { useState, useMemo } from "react";
import { StyleSheet, Text, View } from "react-native";
import RandomNumber from "./RandomNumber";

export default function Game(props) {
  const [state, setstate] = useState([]);
  // 用useMemo缓存随机数和目标值,仅当props.randomNumberCount变化时才重新生成
  const { randomNumber, target } = useMemo(() => {
    const randomNumber = Array.from({ length: props.randomNumberCount }).map(
      () => 1 + Math.floor(10 * Math.random())
    );
    const target = randomNumber
      .slice(0, props.randomNumberCount - 2)
      .reduce((acc, curr) => acc + curr, 0);
    return { randomNumber, target };
  }, [props.randomNumberCount]);

  const isNumberSelected = (numberIndex) => {
    return state.indexOf(numberIndex) >= 0;
  };
  const selectNumber = (numberIndex) => {
    setstate((arr) => [...arr, numberIndex]);
  };
  return (
    <View style={styles.container}>
      <Text style={styles.header}>Target Sum Game</Text>
      <Text style={styles.target}>{target}</Text>
      <View style={styles.randomContainer}>
        {randomNumber.map((randomNumber, index) => (
          <RandomNumber
            key={index}
            id={index}
            number={randomNumber}
            isSelected={isNumberSelected(index)}
            {/* 修复onClick传递逻辑 */}
            onClick={selectNumber}
          />
        ))}
      </View>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#ddd",
    paddingTop: 30,
  },
  target: {
    fontSize: 30,
    backgroundColor: "#aaa",
    margin: 50,
    marginHorizontal: 70,
    textAlign: "center",
  },
  header: {
    fontSize: 35,
    backgroundColor: "dodgerblue",
    textAlign: "center",
    marginHorizontal: 30,
    marginTop: 50,
  },
  randomContainer: {
    flexDirection: "row",
    flexWrap: "wrap",
    justifyContent: "space-around",
  },
});

RandomNumber.js

import React from "react";
import { StyleSheet, Text, TouchableOpacity } from "react-native";

export default function RandomNumber(props) {
  const handlePress = () => {
    props.onClick(props.id);
  };
  return (
    {/* 修复onPress绑定逻辑,不传执行结果,传函数引用 */}
    <TouchableOpacity onPress={handlePress}>
      <Text style={[styles.random, props.isSelected && styles.selected]}>
        {props.number}
      </Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  random: {
    backgroundColor: "#999",
    width: 100,
    marginHorizontal: 35,
    marginVertical: 25,
    fontSize: 35,
    textAlign: "center",
  },
  selected: {
    opacity: 0.3,
  },
});

内容的提问来源于stack exchange,提问作者Rahul Srivastava

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 07:36:07