React Native实现卡片图标单独控制对应List.Accordion的显隐
解决React Native中点击卡片图标仅切换对应List.Accordion显隐的问题
你的问题出在两处关键错误:
- 第二个版本中
ButtonDetail的onPress写法错误:直接调用toggleAccordion(item.id)会在组件渲染时就执行函数,而非点击时触发,导致初始状态混乱。 - 所有
List.Accordion共享同一个全局展开状态:breakfastExpanded是全局状态,不管点击哪个卡片,都会同步修改所有Accordion的展开状态。
下面是修正后的完整代码,同时优化了状态管理逻辑:
export const CategoryScreen = ({ navigation }) => { const { loading, categoryList } = useContext(CategoryContext); // 用对象存储每个item的展开状态,键为item.id,值为布尔值 const [expandedIds, setExpandedIds] = useState({}); const toggleAccordion = (id) => { // 更新对应id的展开状态 setExpandedIds(prevState => ({ ...prevState, [id]: !prevState[id] // 未初始化的id默认是undefined,取反后为true })); }; return ( <SafeArea> {loading && ( <LoadingContainer> <ActivityIndicator animating={true} color={MD2Colors.green200} /> </LoadingContainer> )} <Search /> <CategoryList data={categoryList} renderItem={({ item }) => { const isExpanded = expandedIds[item.id] || false; return ( <> <TouchableOpacity onPress={() => navigation.navigate("groepen", { subcategories: item.id })}> <Spacer position="top" size="large"> <CategoryInfoCard category={item} /> </Spacer> </TouchableOpacity> <View> {/* 用箭头函数包裹,确保点击时才触发toggle */} <ButtonDetail onPress={() => toggleAccordion(item.id)}> <AntDesign name="twitter" size={24} color="green" /> </ButtonDetail> </View> {/* 直接渲染List.Accordion,用isExpanded控制展开状态,避免组件频繁挂载卸载 */} <List.Accordion title="Description" left={(props) => <List.Icon {...props} icon="bird" />} expanded={isExpanded} {/* 点击Accordion本身也可以切换状态,复用toggle函数 */} onPress={() => toggleAccordion(item.id)}> <List.Item title={item.description} /> </List.Accordion> </> ); }} keyExtractor={(item) => item.id} /> </SafeArea> ); };
关键修改说明:
- 状态管理优化:用
expandedIds对象替代数组,直接映射每个item的id和展开状态,查询和更新更高效。 - 修正
onPress调用方式:用() => toggleAccordion(item.id)包裹,确保只有点击时才执行切换逻辑。 - 每个Accordion独立控制:
expanded属性绑定当前item对应的isExpanded状态,实现单独切换。 - 移除冗余的显隐判断:直接渲染
List.Accordion,用其自身的expanded属性控制展开/收起,比条件渲染更流畅。
内容的提问来源于stack exchange,提问作者mightycode Newton
相关产品推荐
相关产品推荐

