React Native(TypeScript) FlatList父子复选框联动功能修复
修复FlatList父子复选框联动逻辑问题
问题分析
当前代码未实现父子复选框的状态联动,导致出现父级(如'Pizzas')未选中但子项已选中的异常。需要实现两个核心联动逻辑:
- 选中父级复选框时,自动勾选该分组下所有子项
- 当某分组下所有子项都取消勾选时,自动取消父级复选框的选中状态
数据结构参考
假设你的数据源结构如下(可根据实际结构调整):
const initialData = [ { id: '1', name: 'Non Veg Biryanis', isSelected: false, children: [ { id: '1-1', name: 'Chicken Biryani', isSelected: false }, { id: '1-2', name: 'Mutton Biryani', isSelected: false } ] }, { id: '2', name: 'Pizzas', isSelected: false, children: [ { id: '2-1', name: 'Pepperoni Pizza', isSelected: false }, { id: '2-2', name: 'Margherita Pizza', isSelected: false } ] } ];
修复后的Accordion组件代码
import React, { useState } from 'react'; import { View, Text, CheckBox, FlatList, StyleSheet } from 'react-native'; const Accordion = () => { const [menuGroups, setMenuGroups] = useState(initialData); // 处理父级复选框切换逻辑 const toggleParent = (parentId) => { setMenuGroups(prevGroups => { return prevGroups.map(group => { if (group.id === parentId) { const newParentState = !group.isSelected; // 同步所有子项的选中状态与父级一致 const updatedChildren = group.children.map(child => ({ ...child, isSelected: newParentState })); return { ...group, isSelected: newParentState, children: updatedChildren }; } return group; }); }); }; // 处理子项复选框切换逻辑 const toggleChild = (parentId, childId) => { setMenuGroups(prevGroups => { return prevGroups.map(group => { if (group.id === parentId) { const updatedChildren = group.children.map(child => { if (child.id === childId) { return { ...child, isSelected: !child.isSelected }; } return child; }); // 判断子项选中状态,更新父级 const allChildrenUnselected = updatedChildren.every(child => !child.isSelected); const allChildrenSelected = updatedChildren.every(child => child.isSelected); return { ...group, children: updatedChildren, isSelected: allChildrenSelected ? true : allChildrenUnselected ? false : group.isSelected }; } return group; }); }); }; // 渲染父项 const renderParentItem = ({ item }) => ( <View style={styles.parentContainer}> <CheckBox value={item.isSelected} onValueChange={() => toggleParent(item.id)} /> <Text style={styles.parentText}>{item.name}</Text> {/* 渲染子项列表 */} <FlatList data={item.children} keyExtractor={child => child.id} renderItem={({ item: child }) => renderChildItem(child, item.id)} nestedScrollEnabled={true} /> </View> ); // 渲染子项 const renderChildItem = (child, parentId) => ( <View style={styles.childContainer}> <CheckBox value={child.isSelected} onValueChange={() => toggleChild(parentId, child.id)} /> <Text style={styles.childText}>{child.name}</Text> </View> ); return ( <FlatList data={menuGroups} keyExtractor={item => item.id} renderItem={renderParentItem} /> ); }; const styles = StyleSheet.create({ parentContainer: { padding: 10, borderBottomWidth: 1, borderBottomColor: '#eee' }, parentText: { fontSize: 16, fontWeight: 'bold' }, childContainer: { flexDirection: 'row', alignItems: 'center', paddingLeft: 20, paddingVertical: 5 }, childText: { fontSize: 14 } }); export default Accordion;
关键逻辑说明
- 父级切换:点击父级复选框时,不仅切换自身选中状态,还会遍历该分组下所有子项,将子项的选中状态同步为父级的新状态,实现全选/全不选效果。
- 子项切换:点击子项后,先切换该子项的状态,再通过
every方法判断所有子项的选中情况:- 若所有子项都未选中 → 父级自动取消选中
- 若所有子项都已选中 → 父级自动选中
- 若部分子项选中 → 父级保持当前状态(可根据需求调整为半选样式,需自定义CheckBox组件)
内容的提问来源于stack exchange,提问作者emma
相关产品推荐
相关产品推荐

