React useState Hook操作数组:点击元素添加索引不生效如何解决
问题原因
你代码有两处核心的事件绑定错误,导致点击事件没有正确触发状态更新:
- Game.js 中给RandomNumber传递onClick的写法错误
你写的是onClick={() => selectNumber},这个箭头函数只是返回了selectNumber函数本身,没有实际执行状态更新逻辑。 - 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
相关产品推荐
相关产品推荐

