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
相关产品推荐
相关产品推荐

