如何通过state修改React Hook Form中的多个复选框选中状态
问题核心原因
- Input属性覆盖问题:你将react-hook-form的
register返回值展开写在input属性最前面,后续自定义的checked、onClick以及空的onChange={() => { }}直接覆盖了register自带的表单监听逻辑,导致表单无法同步复选框状态,全选操作也无法同步到表单数据。 - 全选状态与表单数据脱节:你只维护了子组件内部的选中显示状态,全选时没有主动更新react-hook-form的表单值,导致提交时无法识别全选的内容。
修复方案
第一步:修改Checkbox子组件
调整属性顺序,删除无用的空onChange,避免覆盖register逻辑:
import { useEffect, useState } from "react" import { register } from "react-hook-form" interface CheckboxProps { id: string | undefined, name: string, reg: ReturnType<typeof register>, value: any, label: string, required?: boolean, allChecked: boolean } const Checkbox = ({ id, name, reg, value, label, allChecked }: CheckboxProps) => { const [checked, setChecked] = useState(false); useEffect(() => { setChecked(allChecked); }, [allChecked]) return ( <label key={id}> <input type="checkbox" id={id} value={value} name={name} checked={checked} onClick={() => setChecked(!checked)} {...reg} // register展开放在最后,优先保留它的监听逻辑 /> {label} </label> ) } export default Checkbox;
第二步:修改父组件全选逻辑
全选时主动调用react-hook-form的setValue方法同步表单数据:
// 你之前已经初始化过useForm,直接提取setValue方法即可 const { register, setValue, watch } = useForm(); const [allChecked, setAllChecked] = useState<boolean>(false); // 全选按钮点击事件 const toggleAllChecked = () => { const newStatus = !allChecked; setAllChecked(newStatus); // 同步更新表单字段值 setValue(title as string, newStatus ? [...dataValues] : []); } // 可选补充:手动选中所有复选框时自动同步全选状态 const currentFieldValue = watch(title as string) || []; useEffect(() => { setAllChecked(currentFieldValue.length === dataValues.length); }, [currentFieldValue, dataValues])
可选优化:遍历key优化
你当前遍历用的key={JSON.stringify(e)}性能不佳,直接用生成的slug作为key即可:
dataValues.sort().map((e: any, i: number) => { const slug = e.replace(' ', '-').toLowerCase(); return ( <div key={slug} id={slug}> <Checkbox id={slug} name={title as string} label={e as string} value={e} reg={{ ...register(title as string) }} allChecked={allChecked} /> </div> ) })
内容的提问来源于stack exchange,提问作者Vija Robert
相关产品推荐
相关产品推荐

