React.js中动态存储复选框状态并按指定格式提交API
问题根源
你当前所有权限组(section)共享同一个checkedList状态,导致选中某操作(如Add)时,所有section里的同名复选框会同步选中——因为它们绑定的是同一个数组。要解决这个问题,必须按每个section单独存储选中状态。
分步解决方案
1. 调整父组件状态结构
把单一的checkedList数组改成对象,用section名称作为key,对应的值是该section下选中的权限数组:
// 替换父组件中原有的checkedList状态 const [sectionCheckedLists, setSectionCheckedLists] = useState<Record<string, CheckboxValueType[]>>({}); // 组件挂载时,根据API返回的permissionList初始化每个section的默认选中值 useEffect(() => { if (permissionList.length > 0) { const initialState: Record<string, CheckboxValueType[]> = {}; permissionList.forEach(item => { // 这里沿用你原来的默认选中值,也可以根据需求改成空数组 initialState[item.section] = ["Add", "Update", "Delete", "View"]; }); setSectionCheckedLists(initialState); } }, [permissionList]);
2. 修改父组件的选中状态处理函数
新增带section参数的处理函数,只更新对应section的选中状态:
// 替换父组件中原有的onChange函数 const handleSectionCheckChange = (section: string, list: CheckboxValueType[]) => { setSectionCheckedLists(prev => ({ ...prev, [section]: list })); };
3. 更新CheckBoxItem子组件
让子组件接收当前section的专属参数,调整全选逻辑基于当前section的选项:
// 重新定义子组件的Props interface CheckBoxItemProps { section: string; // 当前权限组名称 checkedList: CheckboxValueType[]; // 当前section的选中列表 onSectionChange: (section: string, list: CheckboxValueType[]) => void; // 带section的更新函数 permissionTitle: string; isGameOption?: boolean; options: CheckboxValueType[]; // 当前section的权限选项(从父组件传入) } const CheckBoxItem: React.FC<CheckBoxItemProps> = (props) => { const { section, checkedList, onSectionChange, options } = props; // 全选/半选逻辑仅针对当前section的选项 const checkAll = options.length === checkedList.length; const indeterminate = checkedList.length > 0 && checkedList.length < options.length; const onCheckAllChange = (event: CheckboxChangeEvent) => { onSectionChange(section, event.target.checked ? options : []); }; const handleChange = (list: CheckboxValueType[]) => { onSectionChange(section, list); }; return ( <> <div className="role-subject-title"> <h3>{props.permissionTitle}</h3> </div> <div className="checkbox-design"> <CheckboxGroup options={options} value={checkedList} onChange={handleChange} className="checkbox-style" /> <Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll} className="checkbox-style-all" > <span style={{ color: "white", fontSize: "20px" }}> {APP_CHECKBOX_ROUTE.CHECK_ALL} </span> </Checkbox> </div> </> ); };
4. 父组件渲染时传递正确参数
遍历permissionList时,给每个CheckBoxItem传入对应section的专属数据:
{permissionList.map((item) => ( <Collapsible title={item.section} isFirst={item === permissionList[0]} key={item.section}> <CheckBoxItem section={item.section} checkedList={sectionCheckedLists[item.section] || []} onSectionChange={handleSectionCheckChange} permissionTitle="" options={item.name} isGameOption={/* 根据你的业务逻辑传true/false,比如判断section是否属于游戏模块 */} /> </Collapsible> ))}
5. 提交时转换为API要求的格式
点击保存按钮时,把状态结构转换成API需要的格式:
const handleSave = () => { const submitData = { name: gameName || "", permissions: permissionList.map(item => ({ section: item.section, name: sectionCheckedLists[item.section] || [] })) }; // 调用接口发送数据 dispatch(addRole(submitData)); }; // 给按钮绑定点击事件 <Button htmlType="submit" className="login-button" onClick={handleSave}> Save </Button>
内容的提问来源于stack exchange,提问作者Shiva Giri
相关产品推荐
相关产品推荐

