React动态表单单选限制及主存储桶已移动项删除问题
问题修复方案
核心问题分析与解决
1. 每个表单只能单选Radio按钮
原代码中所有Radio.Group共享同一个数组value1,导致无法单独控制每个表单的选中状态,出现多选项可同时选中的问题。
- 把
value1从数组改为对象,键为表单id,值为对应选中的选项值,实现每个表单独立管理选中状态。 - 修改
onChange1方法,针对当前表单id更新选中值,而非往数组里push重复数据。 - 每个Radio.Group的
value绑定对应表单id的选中值,保证组内单选。
2. 主Bucket(New Forms Identified)删除已移动项
原代码中NewFormsIdentified是常量,无法修改;同时删除逻辑removeHandler完全错误,无法正确定位要删除的项。
- 将
NewFormsIdentified转为useState状态,允许动态修改。 - 在
onSubmit中,收集所有选中要移动的项,然后过滤主Bucket列表,移除已选中的项。 - 优化
regulatoryData的更新逻辑,避免重复添加相同项。
3. 额外修复:全局编辑状态问题
原edit1是全局布尔值,导致点击编辑时所有表单同时切换编辑状态,改为记录当前编辑的表单id(editId),实现单个表单独立编辑。
修改后完整代码
import React, { useState } from "react"; import { Row, Col, Divider, Button, Radio } from "antd"; import { Hicon, uuid } from "utils/imports"; import styles from "./FormsToBeMaintained.module.css"; const FormsToBeMaintained = props => { const plainOptions = [ { label: "Regulatory Forms", value: "Regulatory Forms" }, { label: "Employer Specific Forms", value: "Employer Specific Forms" } ]; // 改为state,允许动态修改主Bucket列表 const [newFormsIdentified, setNewFormsIdentified] = useState([ { id: 1, tittle: "W-4", "Regulatory Forms": true, "Employer Specific Forms": false, options: [ { labelId: 3, label: "Regulatory Forms", value: "Regulatory Forms" }, { labelId: 4, label: "Employer Specific Forms", value: "Employer Specific Forms" } ] }, { id: 2, tittle: "State new hire tax forms", "Regulatory Forms": true, "Employer Specific Forms": false, options: [ { labelId: 5, label: "Regulatory Forms", value: "Regulatory Forms" }, { labelId: 6, label: "Employer Specific Forms", value: "Employer Specific Forms" } ] }, { id: 3, tittle: "Offer letter", "Regulatory Forms": true, "Employer Specific Forms": false, options: [ { labelId: 7, label: "Regulatory Forms", value: "Regulatory Forms" }, { labelId: 8, label: "Employer Specific Forms", value: "Employer Specific Forms" } ] }, { id: 4, tittle: "Employment agreement", "Regulatory Forms": true, "Employer Specific Forms": false, options: [ { labelId: 9, label: "Regulatory Forms", value: "Regulatory Forms" }, { labelId: 10, label: "Employer Specific Forms", value: "Employer Specific Forms" } ] }, { id: 5, tittle: "Emergency contact information", "Regulatory Forms": true, "Employer Specific Forms": false, options: [ { labelId: 11, label: "Regulatory Forms", value: "Regulatory Forms" }, { labelId: 12, label: "Employer Specific Forms", value: "Employer Specific Forms" } ] } ]); const [radioChecked, isRadioChecked] = useState(false); // 改为对象,存储每个表单id对应的选中值 const [selectedValues, setSelectedValues] = useState({}); // 记录当前编辑的表单id,实现单个表单独立编辑 const [editId, setEditId] = useState(null); const [regulatoryData, setRegulatoryData] = useState([]); // 更新单个表单的选中值 const onChange1 = (formId, value) => { const newSelected = { ...selectedValues, [formId]: value }; setSelectedValues(newSelected); // 只要有选中项,就激活保存按钮 isRadioChecked(Object.values(newSelected).some(v => v)); }; const onSubmit = () => { // 收集所有选中要移动的项 const movedItems = newFormsIdentified .filter(form => selectedValues[form.id]) .map(form => ({ id: form.id, name: form.tittle, value: selectedValues[form.id] })); // 合并到regulatoryData,避免重复添加 setRegulatoryData(prev => { const existingIds = new Set(prev.map(item => item.id)); return [...prev, ...movedItems.filter(item => !existingIds.has(item.id))]; }); // 从主Bucket移除已移动的项 setNewFormsIdentified(prev => prev.filter(form => !selectedValues[form.id]) ); // 清空选中状态,重置保存按钮 setSelectedValues({}); isRadioChecked(false); }; // 取消编辑状态 const cancelEdit = () => setEditId(null); return ( <> <Row> <Col span={12} className={`${styles.outerBor} `}> <Row> <Col span={24} className={`text-size-18 ${styles.title} ${styles.section}`}> Regulated Forms </Col> <Divider /> </Row> <Row className={` ${styles.scroll_content}`}> {regulatoryData.length > 0 ? ( regulatoryData.map(form => { if (form.value === "Regulatory Forms") { return ( <> <Col span={24} className={styles.content} key={form.id}> {editId === form.id ? ( <> <Row> <Col span={18}> <b>{form.name}</b> </Col> <Col span={6} className="align-right"> <Hicon icon="Cancel" onClick={cancelEdit} className="text-size-24" /> <Hicon icon="SaveIconWithoutBackground" className="text-size-24" onClick={() => { // 编辑保存逻辑:更新当前项的分类 cancelEdit(); }} /> </Col> </Row> <Row key={form.id}> <Col span={24} className={` ${styles.content}`}> <Radio.Group key={uuid()} options={plainOptions} value={form.value} onChange={(e) => { setRegulatoryData(prev => prev.map(item => item.id === form.id ? { ...item, value: e.target.value } : item ) ); }} className={` ${styles.radioContent} text-bold `} /> </Col> </Row> </> ) : ( <Row> <Col span={20}> <b>{form.name}</b> </Col> <Col span={4} className="align-right"> <Hicon icon="Pencil" className="text-size-24" onClick={() => setEditId(form.id)} /> </Col> </Row> )} </Col> <Divider /> </> ); } return null; }) ) : ( <Col span={24} className={styles.content}> <b>No Forms included</b> </Col> )} </Row> </Col> <Col span={12} className={`${styles.outerBor} `}> <Row> <Col span={24} className={`text-size-18 ${styles.title} ${styles.section}`}> Employer Specific Forms </Col> <Divider /> </Row> <Row className={` ${styles.scroll_content}`}> {regulatoryData.length > 0 ? ( regulatoryData.map(form => { if (form.value === "Employer Specific Forms") { return ( <> <Col span={24} className={styles.content} key={form.id}> {editId === form.id ? ( <> <Row> <Col span={18}> <b>{form.name}</b> </Col> <Col span={6} className="align-right"> <Hicon icon="Cancel" onClick={cancelEdit} className="text-size-24" /> <Hicon icon="SaveIconWithoutBackground" className="text-size-24" onClick={() => { // 编辑保存逻辑 cancelEdit(); }} /> </Col> </Row> <Row key={form.id}> <Col span={24} className={` ${styles.content}`}> <Radio.Group key={uuid()} options={plainOptions} value={form.value} onChange={(e) => { setRegulatoryData(prev => prev.map(item => item.id === form.id ? { ...item, value: e.target.value } : item ) ); }} className={` ${styles.radioContent} text-bold `} /> </Col> </Row> </> ) : ( <Row> <Col span={20}> <b>{form.name}</b> </Col> <Col span={4} className="align-right"> <Hicon icon="Pencil" className="text-size-24" onClick={() => setEditId(form.id)} /> </Col> </Row> )} </Col> <Divider /> </> ); } return null; }) ) : ( <Col span={24} className={styles.content}> <b>No Forms included</b> </Col> )} </Row> </Col> </Row> <Row> <Col span={24} className={styles.outerBor}> <Row> <Col span={10} className={`text-size-18 text-bold ${styles.title} ${styles.section}`}> New Forms Identified </Col> <Col span={8} className={`text-size-18 text-bold ${styles.title} ${styles.section}`}> Move To </Col> <Col span={6} className={`text-size-18 ${styles.title} ${styles.section}`}> {radioChecked ? ( <div className="align-right"> <Button onClick={() => { setSelectedValues({}); isRadioChecked(false); }} type="text" className="text-size-14" > Cancel </Button> <Button className={` border-radius-5 background_144182 text-size-14`} type="primary" onClick={onSubmit} > <Hicon icon="SaveIconWithoutBackground" className="text-size-16"> <span className="text-size-14">Save</span> </Hicon> </Button> </div> ) : ( <Button className={` border-radius-5 background_144182 text-size-14 align-right`} type="primary" disabled > <Hicon icon="SaveIconWithoutBackground" className="text-size-16"> <span className="text-size-14">Save</span> </Hicon> </Button> )} </Col> </Row> <Divider /> <Row className={` ${styles.scroll_content}`}> {newFormsIdentified.length > 0 ? ( newFormsIdentified.map(form => { return ( <> <Col span={10} className={styles.content} key={form.id}> <ul className="color_144182 text-bold">{form.tittle} </ul> </Col> <Col span={14} className={` ${styles.content}`}> <Radio.Group key={form.id} onChange={(e) => onChange1(form.id, e.target.value)} value={selectedValues[form.id] || undefined} className={` ${styles.radioContent} text-bold `} > {form.options.map(opt => ( <Radio key={opt.labelId} value={opt.value}>{opt.value}</Radio> ))} </Radio.Group> </Col> <Divider /> </> ); }) ) : ( <Col span={24} className={styles.content}> <b>No Forms available</b> </Col> )} </Row> </Col> </Row> </> ); }; export default FormsToBeMaintained;
内容的提问来源于stack exchange,提问作者Swapnil Bais
相关产品推荐
相关产品推荐

