React Native组件渲染时onPress无限触发 点击事件不生效
问题根因
- 无限循环渲染:你在函数组件顶层直接执行
fetchData(),每次组件渲染都会发起请求,请求结束后setUsers会触发组件重渲染,重渲染又会再次调用fetchData(),形成死循环。另外你用的xxx.bind(this)写法在函数组件中无效,每次渲染执行bind都会生成新的函数引用,也会触发不必要的重渲染。 - onPress事件无响应:首先函数组件没有类组件的实例
this,你写的this.storeData本身就是undefined,绑定的处理函数根本不存在;其次Ionicons、FontAwesome这类纯展示图标组件本身不接收onPress属性,无法直接响应点击事件。
修复步骤
- 把顶层直接调用的
fetchData()移入useEffect,依赖项传空数组,保证只在组件首次挂载时执行一次 - 移除所有事件绑定里的
this相关写法,函数组件内直接引用声明的函数即可,需要传固定参数时用箭头函数包裹 - 所有需要响应点击的图标外层包裹可点击组件(推荐用
Pressable,也可以用TouchableOpacity),将onPress绑定到可点击组件上 - 补全原代码中未闭合的JSX标签
修复后核心代码
import { View, Text, TextInput, ScrollView, Pressable } from 'react-native'; import { Ionicons, FontAwesome } from '@expo/vector-icons'; import { useState, useEffect } from 'react'; function SearchScreen({ navigation }) { const [text, setText] = useState('') const [users, setUsers] = useState([]) const fetchData = (category) => { fetch("https://stonernautz.com/companies.json") .then(response => response.json()) .then(data => { setUsers(data) }) } const storeData = async (value) => { try { await AsyncStorage.setItem('searchText', value) getData() } catch (e) {} } const getData = async () => { try { const value = await AsyncStorage.getItem('searchText') setText(value || '') } catch(e) {} } // 首次挂载时执行数据请求和缓存读取 useEffect(() => { fetchData() getData() }, []) const txtHandler = (enteredName) => { setText(enteredName); }; const btnHandler = (icon) => { console.log(icon) } return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor:"black",color:"white"}}> <Text style={{position:"absolute", top:50, left:90,fontSize:20, color:'white'}}>Search</Text> <Ionicons name="location" color={'white'} size={26} style={{position:"absolute", top:50, left:490,fontSize:20}}/> <TextInput style={{ backgroundColor:"white", height: 40, margin: 12, borderWidth: 1, padding: 10, width:"70%", position:"absolute", top:80, borderRadius:10 }} placeholder="Search HUB Businesses..." onChangeText={txtHandler} defaultValue={text} /> <View style={styles.scrollView}> <ScrollView style={styles.scrollView} horizontal={true}> <View style={styles.catView}> <Ionicons name="cafe" color={'white'} size={26} style={{marginLeft:0, marginTop:10}}/> <Text style={{color:"white"}}>Cafe</Text> </View> <View style={styles.catView}> <Pressable onPress={() => storeData('pizza')}> <Ionicons name="pizza" color={'white'} size={26} style={{marginLeft:0, marginTop:10}}/> </Pressable> <Text style={{color:"white"}}>Pizza</Text> </View> <View style={styles.catView}> <Pressable onPress={() => storeData('travel')}> <Ionicons name="paper-plane" color={'white'} size={26} style={{marginLeft:0, marginTop:10}}/> </Pressable> <Text style={{color:"white"}}>Travel</Text> </View> <Pressable style={styles.catView} onPress={() => btnHandler('tree')}> <Pressable onPress={() => storeData('tree')}> <FontAwesome name="tree" color={'white'} size={26} style={{marginLeft:0, marginTop:10}}/> </Pressable> <Text style={{color:"white"}} >Tree</Text> </Pressable> </ScrollView> </View> </View> ) }
提示:如果需要点击整个分类区域触发事件,把
onPress绑定到外层包裹分类的Pressable上即可,不需要给图标单独再套一层。
内容的提问来源于stack exchange,提问作者King Of Missionary
相关产品推荐
相关产品推荐

