无法 check/uncheck 复选框

Unable to check/uncheck the checkbox

我正在制作一个 React 应用程序,其中职位名称的复选框是从 api 的动态数据中填充的,它将与给定的代码段完全一样。

const departments = 
[
   {
      "sectorId":29,
      "sectorName":"Building Materials Mfg. & Distribution",
      "departments":[
         {
            "deptName":"Manufacturing",
            "jobTitles":[
               {
                  "453":false,
                  "JobTitleID":453,
                  "DepartmentID":101,
                  "JobName":"Consultant",
                  "Deleted":false,
                  "SortOrder":5
               },
               {
                  "323":true,
                  "JobTitleID":323,
                  "DepartmentID":101,
                  "JobName":"Quality Control",
                  "Deleted":false,
                  "SortOrder":1
               }
            ]
         },
         {
            "deptName":"Warehouse",
            "jobTitles":[
               {
                  "326":false,
                  "JobTitleID":326,
                  "DepartmentID":98,
                  "JobName":"Warehouse Supervisor",
                  "Deleted":false,
                  "SortOrder":1
               }
            ]
         },
         {
            "deptName":"Administration",
            "jobTitles":[
               {
                  "384":true,
                  "JobTitleID":384,
                  "DepartmentID":115,
                  "JobName":"Controller",
                  "Deleted":false,
                  "SortOrder":1
               }
            ]
         }
      ]
   }
]

  const handleJobTitle = (event, job) => {
    const { checked } = event.target;
    if (checked) {
      document.getElementById(job.JobTitleID).checked = true;
    } else {
      document.getElementById(job.JobTitleID).checked = false;
    }
    console.log(document.getElementById(job.JobTitleID));
  };


const App = () => (
 <div> {departments && departments.map((levelOne, i) => (
            <div
              key={i}
            >
              <p> {levelOne.sectorName} </p>
              {levelOne.departments.map((levelTwo, j) => (
                <div key={j}>
                  <p >
                    {" "}
                    {levelTwo.deptName}{" "}
                  </p>
                  {levelTwo.jobTitles.map((job, l) => (
                    <div
                      key={l}
                    >
                      <input type="checkbox" id={job.JobTitleID} onChange={(e) => {handleJobTitle(e, job)}} name={job.JobName} checked={job[job.JobTitleID]}/>
                      <span>{job.JobName}</span>
                    </div>
                  ))}
                </div>
              ))}
            </div>
          ))} </div>
)

// Render it
ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

这里的 jobTitles 数据会是这样的,

"jobTitles":[
   {
      "453":false,
      "JobTitleID":453,
      "DepartmentID":101,
      "JobName":"Consultant",
      "Deleted":false,
      "SortOrder":5
   },
   {
      "323":true,
      "JobTitleID":323,
      "DepartmentID":101,
      "JobName":"Quality Control",
      "Deleted":false,
      "SortOrder":1
   }
]

然后我根据 "453":false 的值制作复选框 checked,例如,

<input type="checkbox" ...... checked={job[job.JobTitleID]}/>

这里选中了复选框,但是当我尝试取消选中 onChange 处理程序中的复选框时,

const handleJobTitle = (event, job) => { 
 document.getElementById(job.JobTitleID).checked = false;
}

复选框未被选中。如果我 console/inspect 输入元素,则 checked 属性 未删除

附加信息: 也无法选中处于 unchecked 状态的复选框。所以通常我无法对复选框进行任何更改..

任何人都可以帮助我实现解决方案,因为我是新手,所以我被困了太久..

非常感谢。

您需要在输入标签中定义一个 Id 参数。

<input type="checkbox" id="JobTitleCheckBox" ...... checked={job[job.JobTitleID]}/>

然后使用该 ID 获取节点并更改其状态

const handleJobTitle = (event, job) => {
   document.getElementById(job.JobTitleID).checked = false;
}

问题

直接 DOM 突变是反应中的一个 anti-pattern(它在反应之外,所以反应不知道要重新渲染)。

处理程序也不访问 onChange 事件的 checked 属性。

const { checked } = event; // <-- should be event.target

解决方案

使用react state维护组件状态下的checked状态

departments 数据移动到组件状态。

const [departments, setDepartments] = useState(departmentsData);

handleJobTitle 处理程序移动到组件中。我建议使用接受部门 ID、部门名称和工作 ID 的柯里化函数,您将需要这些来“追踪”到正确嵌套对象的路径。您无需担心从 event.target 获取 checked 属性,因为您可以通过 JobTitleID 键值简单地反转状态中的 checked 值。

这里的想法是将任何嵌套状态浅复制到正在更新的新对象引用中以进行反应。

const handleJobTitle = (sectorId, deptName, JobTitleID) => () => {
  setDepartments((data) =>
    data.map((sector) =>
      sector.sectorId === sectorId
        ? {
            ...sector,
            departments: sector.departments.map((dept) =>
              dept.deptName === deptName
                ? {
                    ...dept,
                    jobTitles: dept.jobTitles.map((job) =>
                      job.JobTitleID === JobTitleID
                        ? {
                            ...job,
                            [JobTitleID]: !job[JobTitleID]
                          }
                        : job
                    )
                  }
                : dept
            )
          }
        : sector
    )
  );
};

现在只需将 handleJobTitle 附加到输入的 onChange 处理程序。

<input
  type="checkbox"
  id={job.JobTitleID}
  onChange={handleJobTitle( // <-- pass the required values
    levelOne.sectorId,
    levelTwo.deptName,
    job.JobTitleID
  )}
  name={job.JobName}
  checked={job[job.JobTitleID]}
/>