【问题标题】:Unable to check/uncheck the checkbox无法选中/取消选中复选框
【发布时间】:2021-02-12 16:30:50
【问题描述】:

我正在制作一个反应应用程序,其中职位的复选框是从 api 的动态数据中填充的,它将与给定的 sn-p 完全相同。

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;
}

复选框未被选中。如果我控制台/检查输入元素,则checked 属性未删除

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

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

非常感谢。

【问题讨论】:

  • 直接 DOM 操作/突变的问题在于,这发生在 反应生态系统之外; react 不知道要重新渲染以更新 UI。 job[job.JobTitleID] 值不在反应状态/道具中,并且永远不会更新。
  • @DrewReese,感谢您的来信。您能帮我实现使用状态的结果吗?我从上面的 api 中获得了数据并相应地填充了复选框。所以唯一的问题是选中/取消选中复选框不起作用,我可以理解你的解释。所以你能否使用state/props 为我提供一个正确的解决方案这种情况请..
  • @DrewReese,兄弟你能帮我解决一个问题,我从你之前的答案中得到了解决方案,但它不起作用..这里的问题:stackoverflow.com/q/64967082/13270726
  • @DrewReese,如果您在早上帮忙就可以了。我真的相信您是回答有关滚动到相关元素 fieldset 的问题的合适人选。选定的项目。
  • @DrewReese,您是否有机会帮助我解决上述问题?从昨天开始等待您的解决方案..请帮助我 Reese..

标签: javascript html reactjs checkbox


【解决方案1】:

问题

直接 DOM 突变是 react 中的一种反模式(它在 react 之外,因此 react 无法知道重新渲染)。

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

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

解决方案

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

departments 数据移动到组件状态。

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

handleJobTitle 处理程序移动到组件中。我建议使用接受部门 id、部门名称和工作 id 的 curried 函数,您将需要这些来“跟踪”正确嵌套对象的路径。您无需担心从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]}
/>

【讨论】:

  • 感谢您的快速帮助.. 非常感谢.. 不修改原始数据就不能做事吗?因为您已经删除了职位 ID 并使用布尔值放置了检查。所以如果不修改该部分就不可能吗?
  • @Undefined 那是为了快速演示...您可以在组件安装时处理数据并计算选中的属性,并且不需要删除那些奇怪的键值(到一个新的对象/数组引用 OFC)。对于处理程序,最好有一个一致的键/属性来测试。让我用你必须的动态键来看看我能做什么。
  • @Undefined 更新了使用动态键且不需要更改/添加源数据的解决方案。
  • 你太棒了,感谢你对我的要求做出的改变。向你学习很多东西,我再次感谢你的帮助。
【解决方案2】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-14
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多