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

React 18.2实现分组复选框(每组限选2个)及提交验证

按组选择球队的复选框实现方案(每组最多选2支)

需求与问题

需要实现按组选择球队的复选框功能,要求每组最多只能选择2支球队。使用React 18.2版本,已实现部分选择逻辑,但不清楚如何在提交时将所有选中值汇总到一个数组中,并完成验证。

修改后的完整代码

import { useState } from "react";
const data = [
  {
    group: "A",
    teams: [
      {
        country: "Ecuador",
        country_code: "ECU",
        selected: false,
        admin_selected: true,
        points: 0
      },
      {
        country: "Netherlands",
        country_code: "NED",
        selected: false,
        admin_selected: false,
        points: 0
      },
      {
        country: "Qatar",
        country_code: "QAT",
        selected: false,
        admin_selected: false,
        points: 0
      }
    ]
  },
  {
    group: "B",
    teams: [
      {
        country: "IR Iran",
        country_code: "IRN",
        selected: false,
        admin_selected: false,
        points: 0
      },
      {
        country: "United States",
        country_code: "USA",
        selected: false,
        admin_selected: false,
        points: 0
      },
      {
        country: "England",
        country_code: "ENG",
        selected: false,
        admin_selected: false,
        points: 0
      }
    ]
  },
  {
    group: "C",
    teams: [
      {
        country: "Argentina",
        country_code: "ARG",
        selected: false,
        admin_selected: false,
        points: 0
      },
      {
        country: "Mexico",
        country_code: "MEX",
        selected: false,
        admin_selected: false,
        points: 0
      },
      {
        country: "Poland",
        country_code: "POL",
        selected: false,
        admin_selected: false,
        points: 0
      }
    ]
  }
];

export default function App() {
  // 按组存储选中的球队编码,结构:{ 组名: [选中的code数组] }
  const [selectedByGroup, setSelectedByGroup] = useState(() => {
    // 初始化每个组的选中状态为空数组
    return data.reduce((acc, group) => {
      acc[group.group] = [];
      return acc;
    }, {});
  });

  const handleTeamSelect = (groupName, teamCode, isChecked) => {
    setSelectedByGroup(prev => {
      const currentSelected = prev[groupName] || [];
      let newSelected;

      if (isChecked) {
        // 选中时检查是否已选满2支
        if (currentSelected.length >= 2) {
          alert(`组${groupName}最多只能选择2支球队`);
          return prev;
        }
        newSelected = [...currentSelected, teamCode];
      } else {
        // 取消选中时过滤掉对应的code
        newSelected = currentSelected.filter(code => code !== teamCode);
      }

      return {
        ...prev,
        [groupName]: newSelected
      };
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    
    // 1. 验证逻辑:检查每个组的选中数量是否符合要求(这里示例为可选0-2,若要求必须选2则调整)
    const invalidGroups = Object.entries(selectedByGroup).filter(([group, selected]) => {
      // 若要求每组必须选2支,改为 selected.length !== 2
      return selected.length > 2;
    });

    if (invalidGroups.length > 0) {
      alert(`以下组选择不符合要求:${invalidGroups.map(([group]) => group).join(', ')}`);
      return;
    }

    // 2. 汇总所有选中的球队编码到一个数组
    const allSelectedTeams = Object.values(selectedByGroup).flat();
    console.log('所有选中的球队编码:', allSelectedTeams);
    
    // 这里可以添加提交到后端的逻辑
    alert(`已选中${allSelectedTeams.length}支球队:${allSelectedTeams.join(', ')}`);
  };

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        {data.map((group) => (
          <SingleGroup
            key={group.group}
            groupData={group}
            selectedTeams={selectedByGroup[group.group]}
            onTeamSelect={handleTeamSelect}
          />
        ))}
        <button type="submit">提交</button>
      </form>
    </div>
  );
}

const SingleGroup = ({ groupData, selectedTeams, onTeamSelect }) => {
  return (
    <div>
      <h4>Group: {groupData.group}</h4>
      {groupData.teams.map((team) => (
        <label key={team.country_code} style={{ display: 'block', margin: '4px 0' }}>
          <input
            type="checkbox"
            name={team.country_code}
            value={team.country_code}
            checked={selectedTeams.includes(team.country_code)}
            onChange={(e) => onTeamSelect(groupData.group, team.country_code, e.target.checked)}
          />
          {team.country}
        </label>
      ))}
    </div>
  );
};

关键改动说明

  • 统一状态管理:将所有组的选中状态提升到父组件App中,以{ 组名: [选中的球队编码数组] }的结构存储,避免子组件独立状态导致的汇总困难。
  • 选择逻辑优化:在父组件中处理每组的选择限制(最多2支),子组件仅负责渲染复选框并传递选择事件,逻辑更清晰。
  • 提交时的验证与汇总:
    • 验证阶段:遍历所有组的选中数据,检查是否存在不符合要求的组(如选中数量超过2)。
    • 汇总阶段:使用Object.values(selectedByGroup).flat()将所有组的选中数组合并为一个一维数组,方便后续处理。
  • 受控组件实现:复选框的checked状态由父组件传递的selectedTeams控制,确保UI与状态一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:09:22