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

React Native组件渲染时onPress无限触发 点击事件不生效

问题根因
  • 无限循环渲染:你在函数组件顶层直接执行fetchData(),每次组件渲染都会发起请求,请求结束后setUsers会触发组件重渲染,重渲染又会再次调用fetchData(),形成死循环。另外你用的xxx.bind(this)写法在函数组件中无效,每次渲染执行bind都会生成新的函数引用,也会触发不必要的重渲染。
  • onPress事件无响应:首先函数组件没有类组件的实例this,你写的this.storeData本身就是undefined,绑定的处理函数根本不存在;其次Ionicons、FontAwesome这类纯展示图标组件本身不接收onPress属性,无法直接响应点击事件。
修复步骤
  1. 把顶层直接调用的fetchData()移入useEffect,依赖项传空数组,保证只在组件首次挂载时执行一次
  2. 移除所有事件绑定里的this相关写法,函数组件内直接引用声明的函数即可,需要传固定参数时用箭头函数包裹
  3. 所有需要响应点击的图标外层包裹可点击组件(推荐用Pressable,也可以用TouchableOpacity),将onPress绑定到可点击组件上
  4. 补全原代码中未闭合的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 03:09:20