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

React Native(TypeScript) FlatList父子复选框联动功能修复

修复FlatList父子复选框联动逻辑问题

问题分析

当前代码未实现父子复选框的状态联动,导致出现父级(如'Pizzas')未选中但子项已选中的异常。需要实现两个核心联动逻辑:

  1. 选中父级复选框时,自动勾选该分组下所有子项
  2. 当某分组下所有子项都取消勾选时,自动取消父级复选框的选中状态

数据结构参考

假设你的数据源结构如下(可根据实际结构调整):

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;

关键逻辑说明

  1. 父级切换:点击父级复选框时,不仅切换自身选中状态,还会遍历该分组下所有子项,将子项的选中状态同步为父级的新状态,实现全选/全不选效果。
  2. 子项切换:点击子项后,先切换该子项的状态,再通过every方法判断所有子项的选中情况:
    • 若所有子项都未选中 → 父级自动取消选中
    • 若所有子项都已选中 → 父级自动选中
    • 若部分子项选中 → 父级保持当前状态(可根据需求调整为半选样式,需自定义CheckBox组件)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:45:31