如何使用Hooks和函数式组件修改FlatList单个选中项的样式
React Native FlatList单选高亮实现方案
核心问题定位
你当前无法实现互斥选中的根本原因是:每个RenderCategories子组件都独立维护了自己的selected、selectedId状态,兄弟组件之间状态完全隔离,选中新项时无法通知旧选中项更新状态。
实现逻辑调整
我们需要把选中状态提升到父组件CategoriesList统一维护,所有子项的选中状态都由父组件的唯一选中ID控制,具体修改如下:
1. 修改CategoriesList组件
在父组件中维护当前激活的选中ID,定义选中处理逻辑,将状态和方法传递给子组件:
import { useState } from 'react'; const CategoriesList = ()=> { // 维护当前选中的项ID,默认初始值为'1'(对应默认选中第一项) const [activeId, setActiveId] = useState('1'); // 选中处理逻辑 const handleSelect = (id) => { // 如果点击的是当前已选中项,就取消选中;否则切换为新点击的项 setActiveId(prev => prev === id ? null : id); } return ( <View style = {styles.categoriesListContainer}> <FlatList contentContainerStyle={{ paddingRight :120 }} data = {categoriesData} renderItem = {({item}) => <RenderCategories item={item} activeId={activeId} onSelect={handleSelect} />} keyExtractor = {(item) => item.id} horizontal = {true} /> </View> ) }
2. 修改RenderCategories组件
删除子组件内部的选中状态,直接通过父组件传递的参数判断选中状态,点击时调用父组件的选中方法:
const RenderCategories = ({item, activeId, onSelect}) => { // 直接通过ID匹配判断当前项是否选中,不用内部维护状态 const selected = activeId === item.id; return ( <TouchableOpacity onPress = {()=> onSelect(item.id)}> <View style = {[styles.listItems, {backgroundColor : selected ? colors.primary : "#fff"}]}> <Image resizeMode = "stretch" source = {item.image} style = {styles.listItemImage}/> <Text style = {styles.listItemTitle}>{item.title}</Text> <View style = {[styles.iconwrapper, {backgroundColor : selected ? "#fff" : colors.secondary}]}> <Feather name = "chevron-right" size = {8} style = {[styles.categoryiconselect, {backgroundColor : selected ? "#fff" : colors.secondary}]}/> </View> </View> </TouchableOpacity> ) }
实现效果说明
修改后所有子项的选中状态都由父组件的activeId统一控制,每次选中新项时更新activeId,所有子项都会自动重新匹配ID、更新选中状态,既保留了你原有二次点击取消选中的能力,也实现了新项选中时旧项自动取消高亮的互斥效果。
内容的提问来源于stack exchange,提问作者Furrukh Jamal
相关产品推荐
相关产品推荐

