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

React Atlaskit受控Checkbox无法取消勾选问题解决

问题根源

你当前的复选框被写成了只读受控组件:手动传入了固定计算的isChecked属性,但没有绑定用户勾选/取消时的状态更新逻辑,导致不管用户怎么点击,isChecked始终是初始计算出的值,自然无法取消勾选。
另外你已经用了@atlaskit/form的CheckboxField组件,它本身会自动托管表单字段的状态,你强行传入固定isChecked会直接覆盖组件内部的状态更新,这是导致交互失效的核心原因。

修复方案

优先选第一种方案,和你现有表单逻辑适配度最高,不需要额外写状态维护代码。

方案1:使用表单默认值属性(推荐)

不要手动给Checkbox传isChecked,把初始选中状态传给CheckboxField的defaultIsChecked属性,交给表单组件自己管理勾选状态,它会自动处理用户的勾选/取消操作,提交时也能正常拿到最新值。
把原来循环里的复选框渲染代码替换成下面的内容:

sentinelVulnerabilities.map((element) => {
    const isChecked = shouldBeChecked(element.value);
    return <div>
        <Grid spacing="compact" columns={columns}>
            <GridColumn medium={4} css={{paddingTop: '5px'}}>
                {/* 把初始值传给CheckboxField的defaultIsChecked,不要给Checkbox传isChecked */}
                <CheckboxField 
                    name="vulnerabilities" 
                    value={element.value}
                    defaultIsChecked={isChecked}
                >
                    {({fieldProps}) => <Checkbox {...fieldProps} label={element.label} />}
                </CheckboxField>
            </GridColumn>
            <GridColumn medium={8}>
                <Field<Value<Option>>
                    name={element.value}
                    isRequired={true}
                    defaultValue={{
                        value: shouldBySelected(element.value).toLowerCase(),
                        label: shouldBySelected(element.value)
                    }}
                >
                    {/* 原代码漏写了Select渲染,必须补上不然下拉框不显示 */}
                    {({fieldProps}) => <Select {...fieldProps} options={jiraIssuePrioritiesOptions} />}
                </Field>
            </GridColumn>
        </Grid>
    </div>;
})

改完之后表单会自动维护选中状态,提交时data.vulnerabilities就是当前所有勾选的漏洞值数组,和你原来的onSubmit逻辑完全兼容,不需要改动提交逻辑。

方案2:自行维护受控状态(不推荐)

如果你一定要自己控制所有复选框的选中状态,需要手动监听change事件更新状态,同时同步触发表单的内部更新,不然提交时拿不到最新值:

  1. 先修正状态初始值,加加载状态避免异步数据导致的初始值错误:
const [allowedVul, setAllowedVul] = useState<string[]>([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
    (async () => {
        const res = await invoke("getStorage", {name: 'vulnerabilities_allowed'});
        setAllowedVul(Array.isArray(res) ? res : []);
        setLoading(false);
    })();
}, [])
  1. 写复选框变化的处理逻辑:
const handleVulnCheckChange = (vulnValue: string, checked: boolean) => {
    setAllowedVul(prev => {
        if (checked) {
            return prev.includes(vulnValue) ? prev : [...prev, vulnValue]
        } else {
            return prev.filter(item => item !== vulnValue)
        }
    })
}
  1. 渲染时绑定事件和受控值:
{loading ? <div>配置加载中...</div> : sentinelVulnerabilities.map((element) => {
    const isChecked = allowedVul.includes(element.value);
    return <div>
        <Grid spacing="compact" columns={columns}>
            <GridColumn medium={4} css={{paddingTop: '5px'}}>
                <CheckboxField name="vulnerabilities" value={element.value}>
                    {({fieldProps}) => <Checkbox 
                        {...fieldProps} 
                        label={element.label} 
                        isChecked={isChecked}
                        onChange={(e) => {
                            fieldProps.onChange(e); // 必须调用,同步给表单状态
                            handleVulnCheckChange(element.value, e.target.checked);
                        }}
                    />}
                </CheckboxField>
            </GridColumn>
            {/* 下拉框逻辑和之前一致 */}
        </Grid>
    </div>;
})}
其他需要修正的笔误
  • shouldBySelected和shouldBeChecked函数里判断长度的代码末尾多了个多余的.,属于语法错误,要删掉,改成Object.keys(xxx).length === 0
  • allowedVul是数组类型,判断空直接用allowedVul.length === 0即可,不需要调用Object.keys

内容的提问来源于stack exchange,提问作者user2994290

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:01:09