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

如何通过state修改React Hook Form中的多个复选框选中状态

问题核心原因

  1. Input属性覆盖问题:你将react-hook-form的register返回值展开写在input属性最前面,后续自定义的checked、onClick以及空的onChange={() => { }}直接覆盖了register自带的表单监听逻辑,导致表单无法同步复选框状态,全选操作也无法同步到表单数据。
  2. 全选状态与表单数据脱节:你只维护了子组件内部的选中显示状态,全选时没有主动更新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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:15:03