React Native中TouchableOpacity的onPress需二次点击才生效问题
问题解决:React Native FlatList 新增条目后首次删除无响应
问题根源
你碰到的是典型的闭包捕获旧状态问题:
addGoalHandler和deleteItem里直接使用了当前的goalsList变量,当组件重新渲染时,这些函数捕获的是创建时的旧状态引用。- 刚添加新条目后,第一次点击删除时,函数里的
goalsList还是更新前的旧数组,过滤后和原数组没有变化,所以看起来没生效;第二次点击时,组件已经完成重新渲染,函数捕获了新的状态,才能正确执行删除操作。
修复方案
把状态更新改成函数式更新,让React自动传入最新的状态值,彻底规避闭包带来的旧引用问题:
修改后的App.js
import { useState } from "react"; import { StyleSheet, Text, View, FlatList, TouchableOpacity } from "react-native"; import GoalInput from "./components/GoalInput"; export default function App() { const [goalsList, setGoalsList] = useState([]); // 用函数式更新获取最新状态 const addGoalHandler = (goal) => { setGoalsList(prevGoals => [...prevGoals, { text: goal, id: Math.random().toString() }]); }; // 同样使用函数式更新删除条目 const deleteItem = (itemId) => { setGoalsList(prevGoals => prevGoals.filter((goal) => goal.id !== itemId)); }; return ( <View style={styles.container}> <GoalInput onAddGoal={addGoalHandler} /> <View style={styles.goalsContainer}> <FlatList alwaysBounceVertical={false} data={goalsList} keyExtractor={(item) => item.id} renderItem={(itemData) => { return ( <TouchableOpacity onPress={() => deleteItem(itemData.item.id)}> <Text style={{ fontSize: 40, backgroundColor: "purple", color: "white", margin: 10, borderRadius: 10, }} > {itemData.item.text} </Text> </TouchableOpacity> ); }} /> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "white", marginHorizontal: 15, }, goalsContainer: { flex: 3, }, });
关键改动说明
- 所有状态更新都改用
setGoalsList(prevGoals => ...)的形式:通过React传入的prevGoals参数获取当前最新的状态数组,确保每次操作都是基于最新数据执行的。 - 这样修改后,不管是新增条目还是删除条目,都能直接拿到最新状态,新增后首次点击删除也能立即生效,不会再出现无响应的情况。
内容的提问来源于stack exchange,提问作者Noam B.
相关产品推荐
相关产品推荐

