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
相关产品推荐
相关产品推荐

