React Native中TouchableOpacity onPress多次触发导航重复跳转问题
解决快速点击导致多次导航的问题
方案1:防抖函数限制触发频率
通过防抖函数确保短时间内(默认300ms)只有第一次点击生效,后续重复点击会被忽略。
先定义防抖工具函数:
const debounce = (func, delay = 300) => { let timerId; return (...args) => { if (timerId) clearTimeout(timerId); timerId = setTimeout(() => func.apply(this, args), delay); }; };
在FlatList所在的父组件中,用防抖包装导航逻辑:
// 定义防抖后的导航函数 const navigateToProduct = debounce((item) => { navigation.push("product_details", { title: `${item.propertyType} ${currencyFormat(item.price)}`, id: item.id }); }); // 传递给ProductCard <ProductCard favorites={favorites} onPress={() => navigateToProduct(item)} index={index} data={item} style={[ favorites.length % 2 === 1 && index === favorites.length - 1 && {marginRight: 28} ]} />
方案2:状态锁阻止重复点击
在组件内维护一个状态标记是否正在处理导航,点击后立刻锁定,导航完成或超时后解锁。
父组件中处理:
import { useState } from 'react'; // 父组件内定义状态 const [isNavigating, setIsNavigating] = useState(false); const handleNavigate = (item) => { if (isNavigating) return; setIsNavigating(true); navigation.push("product_details", { title: `${item.propertyType} ${currencyFormat(item.price)}`, id: item.id }); // 页面跳转完成后解锁,避免导航失败后一直锁定 const unsubscribe = navigation.addListener('focus', () => { setIsNavigating(false); unsubscribe(); }); }; // 传递给ProductCard <ProductCard onPress={() => handleNavigate(item)} // 其他props... />
ProductCard内部处理:
import { useState } from 'react'; // ProductCard组件内 const [isClicked, setIsClicked] = useState(false); const handlePress = () => { if (isClicked) return; setIsClicked(true); onPress(); // 调用传入的导航函数 // 超时解锁,兜底处理导航失败的情况 setTimeout(() => setIsClicked(false), 500); }; // 修改TouchableOpacity的onPress <TouchableOpacity onPress={handlePress} style={[styles.cardContainer, index % 2 === 0 ? { marginLeft: 15, marginRight: 8 } : { marginLeft: 8, marginRight: 15 }, style]}> // 组件原有内容... </TouchableOpacity>
方案3:替换导航方法(适合无需重复页面场景)
如果业务允许,用navigation.navigate替代push——navigate会检查导航栈中是否已存在目标页面,若存在则直接跳转至该页面,不会新增重复页面:
onPress={() => navigation.navigate("product_details", { title: `${item.propertyType} ${currencyFormat(item.price)}`, id: item.id })}
注意:此方案会改变导航行为,若业务需要允许同一商品打开多个详情页则不适用。
方案4:调整TouchableOpacity响应延迟(不推荐)
通过delayPressIn属性延迟点击事件触发,减少快速点击的可能性,但会影响用户点击体验:
<TouchableOpacity onPress={onPress} delayPressIn={300} // 延迟300ms触发点击 style={[styles.cardContainer, index % 2 === 0 ? { marginLeft: 15, marginRight: 8 } : { marginLeft: 8, marginRight: 15 }, style]} > // 组件原有内容... </TouchableOpacity>
内容的提问来源于stack exchange,提问作者m10
相关产品推荐
相关产品推荐

