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

React Native 标签选择页面点击后出现数秒卡顿问题求助

问题原因

  • 列表key使用Math.random():每次组件重渲染时所有标签项的key都会完全重置,React会销毁整个标签列表再重新创建所有节点,而非增量更新,这是卡顿的核心原因。
  • selected状态外置且使用数组存储:全局外置的selected不属于React状态管控,容易出现状态不同步问题,且数组的includes、indexOf、splice操作都是O(n)复杂度,标签数量多的时候计算开销会大幅上升。
  • 业务逻辑冗余错误:fire1、fire2两个函数逻辑混乱,取消选中的fire2中仍然执行了setInterests([...interests, item])的新增逻辑,存在不必要的状态更新。
  • 重复的组件声明:相同结构的PressableBackground写了两份,每次渲染都会生成大量重复的匿名函数,增加渲染开销。

解决方案

  1. 替换随机key:使用标签本身作为唯一固定key,确保React可以复用组件节点,避免全量销毁重建。
  2. 重构selected状态:将selected移入组件内部用useState管控,同时改为Set类型,将增删查的复杂度降到O(1)。
  3. 合并逻辑删除冗余:将两个点击函数合并为一个,修正选中/取消选中的状态更新逻辑,不需要的冗余状态可以直接删除。
  4. 封装单个标签组件:用React.memo封装单个标签项,结合useCallback缓存点击函数,只更新状态发生变化的标签,其他标签不重渲染。

优化后参考代码

import { useState, useCallback, memo } from 'react'

// 封装单个标签组件,只有item、selected、onPress变化时才会重渲染
const TagItem = memo(({ item, selected, onPress, colors }) => {
  return (
    <PressableBackground onPress={() => onPress(item)}>
      <View style={{margin: 2.5}}>
        <Tag color={selected ? colors.card : undefined}>
          <Text style={{color: selected ? colors.background : colors.text}}>{item}</Text>
        </Tag>
      </View>
    </PressableBackground>
  )
})

const TagScreen = () => {
  const [allInterests] = useState(["interst1", "interst2", "interst3", "interst4", "interst5", "interst6", "interst7", "interst8", "interst9", "interst10"])
  // 用Set存储选中项,操作复杂度O(1)
  const [selected, setSelected] = useState(new Set())
  // 如果后续不需要用到interests状态可以直接删除,这里保留兼容原有逻辑
  const [interests, setInterests] = useState([])

  const toggleTag = useCallback((item) => {
    setSelected(prev => {
      const newSelected = new Set(prev)
      if (newSelected.has(item)) {
        newSelected.delete(item)
        // 同步更新interests,不需要的话可以删掉这段逻辑
        setInterests(prev => prev.filter(i => i !== item))
      } else {
        newSelected.add(item)
        setInterests(prev => [...prev, item])
      }
      return newSelected
    })
  }, [])

  return (
    <View>
      <View style={{display: "flex", flexWrap: "wrap", flexDirection: "row"}}>
        {allInterests.map(item => (
          <View key={item}>
            <TagItem 
              item={item} 
              selected={selected.has(item)} 
              onPress={toggleTag}
              colors={colors}
            />
          </View>
        ))}
      </View>
    </View>
  );
}

export default TagScreen;

内容的提问来源于stack exchange,提问作者Henrik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 05:36:10