React页面加载时仅勾选最后一组复选框问题求助
多组复选框仅最后一组默认选中的修复方案
问题描述
我有两组独立复选框,每组对应专属字段,部分复选框需要在页面加载时默认选中。但目前只有最后一组的复选框能被默认勾选,第一组完全失效;移除第二组后功能恢复正常,添加后问题重现。
原代码
import React, { useState, useEffect } from "react"; import ReactDOM from "react-dom"; import { Checkbox, Pane, Label } from "evergreen-ui"; function ControlledCheckboxExample() { const [checked, setChecked] = React.useState(true); const [fieldchecked, setIsFieldChecked] = React.useState(false); const [editContactFields, setContactFields] = React.useState([]); useEffect(() => { loaddata(); }, []); const loaddata = () => { let data = [ { id: 1, label: "First Checkbox", type: "checkbox", selectedvalue: [ { value: "one" }, { value: "two" } ], hasvalue: true, tag: "UNIQUEONE", options: [ { value: "one", text: "one" }, { value: "two", text: "two" }, { value: "three", text: "three" }, { value: "four", text: "four" } ], visible: true }, { id: 2, label: "Second Checkbox", type: "checkbox", selectedvalue: [ { value: "five" } ], hasvalue: true, tag: "UNIQUETWO", options: [ { value: "five", text: "five" } ], visible: true } ]; setContactFields(data); data.map((field, index) => { if (field.type === "checkbox" && field.hasvalue == true) { setIsFieldChecked(false); let value = field.selectedvalue; let tag = field.tag; value.map((realvalue) => { let fieldvalud = realvalue.value; setIsFieldChecked((fieldchecked) => ({ ...fieldchecked, [fieldvalud + tag]: !fieldchecked[fieldvalud + tag] })); }); } }); }; const handlefieldchecked = (a, f) => { const fieldvalud = a; const tag = f; setIsFieldChecked((fieldchecked) => ({ ...fieldchecked, [fieldvalud + tag]: !fieldchecked[fieldvalud + tag] })); }; return ( <Pane> {editContactFields.map((field) => ( <Pane> <Label> {field.label} {field.required == true && "*"} </Label> {field.options.map((checkboxfield) => ( <Checkbox name={field.tag + "[]"} id={field.tag} type={field.type} value={checkboxfield.value} label={checkboxfield.text} checked={fieldchecked[checkboxfield.value + field.tag]} required={field.required} onChange={(e) => handlefieldchecked(checkboxfield.value, field.tag) } /> ))} </Pane> ))} </Pane> ); } ReactDOM.render(<ControlledCheckboxExample />, document.getElementById("root"));
问题分析
- 初始状态错误:
fieldchecked初始化为false,但它需要存储键值对形式的选中状态映射,应该是一个空对象{}。 - 状态重置覆盖:遍历每组字段时调用
setIsFieldChecked(false),会清空之前设置的第一组选中状态,导致只有最后一组的设置保留。 - 批量更新冲突:React会批量处理多次
setState调用,前面的更新会被后面的重置操作覆盖,最终只保留最后一组的选中状态。
修复方案
步骤1:修正初始状态
将fieldchecked的初始值改为空对象:
const [fieldchecked, setIsFieldChecked] = React.useState({});
步骤2:移除状态重置操作
删除loaddata中遍历字段时的setIsFieldChecked(false),避免清空已设置的状态。
步骤3:构建完整选中状态后一次性更新
预先遍历所有数据,构建好完整的选中状态对象,再一次性调用setState,避免多次更新的冲突:
const loaddata = () => { let data = [/* 原数据 */]; setContactFields(data); // 预先构建选中状态对象 const initialChecked = {}; data.forEach((field) => { if (field.type === "checkbox" && field.hasvalue) { field.selectedvalue.forEach((realvalue) => { const key = `${realvalue.value}${field.tag}`; initialChecked[key] = true; }); } }); setIsFieldChecked(initialChecked); };
修复后的完整代码
import React, { useState, useEffect } from "react"; import ReactDOM from "react-dom"; import { Checkbox, Pane, Label } from "evergreen-ui"; function ControlledCheckboxExample() { const [checked, setChecked] = React.useState(true); // 修正初始状态为对象 const [fieldchecked, setIsFieldChecked] = React.useState({}); const [editContactFields, setContactFields] = React.useState([]); useEffect(() => { loaddata(); }, []); const loaddata = () => { let data = [ { id: 1, label: "First Checkbox", type: "checkbox", selectedvalue: [ { value: "one" }, { value: "two" } ], hasvalue: true, tag: "UNIQUEONE", options: [ { value: "one", text: "one" }, { value: "two", text: "two" }, { value: "three", text: "three" }, { value: "four", text: "four" } ], visible: true }, { id: 2, label: "Second Checkbox", type: "checkbox", selectedvalue: [ { value: "five" } ], hasvalue: true, tag: "UNIQUETWO", options: [ { value: "five", text: "five" } ], visible: true } ]; setContactFields(data); // 一次性构建初始选中状态 const initialChecked = {}; data.forEach(field => { if (field.type === "checkbox" && field.hasvalue) { field.selectedvalue.forEach(realvalue => { const key = `${realvalue.value}${field.tag}`; initialChecked[key] = true; }); } }); setIsFieldChecked(initialChecked); }; const handlefieldchecked = (a, f) => { const fieldvalud = a; const tag = f; setIsFieldChecked((fieldchecked) => ({ ...fieldchecked, [fieldvalud + tag]: !fieldchecked[fieldvalud + tag] })); }; return ( <Pane> {editContactFields.map((field) => ( {/* 添加key避免React渲染警告 */} <Pane key={field.id}> <Label> {field.label} {field.required == true && "*"} </Label> {field.options.map((checkboxfield) => ( {/* 添加唯一key */} <Checkbox key={`${field.tag}-${checkboxfield.value}`} name={field.tag + "[]"} id={`${field.tag}-${checkboxfield.value}`} type={field.type} value={checkboxfield.value} label={checkboxfield.text} checked={fieldchecked[checkboxfield.value + field.tag]} required={field.required} onChange={(e) => handlefieldchecked(checkboxfield.value, field.tag) } /> ))} </Pane> ))} </Pane> ); } ReactDOM.render(<ControlledCheckboxExample />, document.getElementById("root"));
额外优化:给map循环的元素添加了唯一key,避免React渲染警告。
内容的提问来源于stack exchange,提问作者idir
相关产品推荐
相关产品推荐

