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

React Native:点击FlatList元素改样式仅最后一个生效的修复方案

修复FlatList点击元素样式修改异常问题

问题根源

你使用单个useRef存储所有列表项的View引用,FlatList循环渲染时,每个列表项的View都会覆盖这个ref的current值,最终ref只会指向最后一个渲染的元素,因此无论点击哪个列表项,都会修改最后一个元素的样式。


推荐修复方案(状态驱动UI)

React更推荐通过状态控制UI变化,这种方式符合单向数据流,代码更稳定易维护:

import { Text, View, FlatList, TouchableOpacity } from 'react-native'
import React, { useState } from 'react'

const App = () => {
    // 用状态记录当前选中的列表项
    const [selectedItem, setSelectedItem] = useState(null)

    return (
        <View>
            <FlatList
                data={[1, 2, 3, 4, 5]}
                renderItem={({ item }) => (
                    <TouchableOpacity onPress={() => setSelectedItem(item)}>
                        <View 
                            style={{ 
                                backgroundColor: selectedItem === item ? 'blue' : '#eee', 
                                margin: 5, 
                                padding: 20, 
                                alignItems: 'center', 
                                borderRadius: 10 
                            }}
                        >
                            <Text>{item}</Text>
                        </View>
                    </TouchableOpacity>
                )}
                keyExtractor={(item, index) => index.toString()}
            />
        </View>
    )
}

export default App

方案说明:

  • 用useState存储当前选中的列表项,点击时更新状态
  • View的背景色根据selectedItem是否等于当前列表项动态切换
  • 无需直接操作原生组件,完全遵循React的状态驱动逻辑

备选方案(使用Ref数组,适合特殊场景)

如果有必须直接操作原生组件的需求(比如性能优化),可以用Ref数组存储每个列表项的引用:

import { Text, View, FlatList, TouchableOpacity } from 'react-native'
import React, { useRef, useEffect } from 'react'

const App = () => {
    const data = [1, 2, 3, 4, 5]
    // 创建Ref数组,存储每个列表项的View引用
    const itemRefs = useRef([])

    // 初始化Ref数组,长度与数据源一致
    useEffect(() => {
        itemRefs.current = data.map(() => React.createRef())
    }, [data])

    const handleItemClick = (index) => {
        // 可选:重置所有列表项的背景色
        itemRefs.current.forEach(ref => {
            if (ref.current) {
                ref.current.setNativeProps({ style: { backgroundColor: '#eee' } })
            }
        })
        // 修改当前点击列表项的背景色
        itemRefs.current[index].current.setNativeProps({ style: { backgroundColor: 'blue' } })
    }

    return (
        <View>
            <FlatList
                data={data}
                renderItem={({ item, index }) => (
                    <TouchableOpacity onPress={() => handleItemClick(index)}>
                        <View 
                            ref={itemRefs.current[index]} 
                            style={{ 
                                backgroundColor: '#eee', 
                                margin: 5, 
                                padding: 20, 
                                alignItems: 'center', 
                                borderRadius: 10 
                            }}
                        >
                            <Text>{item}</Text>
                        </View>
                    </TouchableOpacity>
                )}
                keyExtractor={(item, index) => index.toString()}
            />
        </View>
    )
}

export default App

方案说明:

  • 用useRef创建数组,每个元素对应一个列表项的View引用
  • 初始化时根据数据源长度生成对应数量的Ref
  • 点击时通过索引找到对应的Ref,修改其原生样式
  • 如果需要单选效果,可先重置所有列表项的样式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 00:10:28