Unable to check/uncheck the checkbox

时光怂恿深爱的人放手 提交于 2021-01-01 08:57:38

问题


I am making a react application where checkboxes for jobtitles are populated from the dynamic data from api and it will be exactly like given snippet.

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>

Here the jobTitles data will be like,

"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
   }
]

And I make the checkbox checked based on the value of "453":false like,

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

And the checkboxes are checked here but when I try to uncheck the checkbox in onChange handler like,

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

The checkboxes are not unchecked.. If I console/inspect the input element then the checked atribute is not removed.

Additional Info: It is also not possible to check the checkbox which is in unchecked state.. So in common I couldn't make any change to checkbox..

Could anybody please help me to achieve the solution and I am got stuck for too long with this as I am new to react..

Big thanks in advance.


回答1:


Issue(s)

Direct DOM mutation is an anti-pattern in react (it is outside react so react can't know to rerender).

The handler also doesn't access the checked property of the onChange event.

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

Solution

Use react state to maintain the checked status in component state.

Move the departments data into component state.

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

Move the handleJobTitle handler into the component. I suggest using a curried function that accepts the sector id, department name, and the job id, you'll need these to "trace" the path to the correct nested object. You don't need to worry about getting the checked property from event.target as you can simply invert a checked value in state via the JobTitleID key value.

The idea here is to shallow copy any nested state, into new object references for react, that is being updated.

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

Now simply attach the handleJobTitle to the input's onChange handler.

<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]}
/>




回答2:


You need to define an Id parameter in the input tag.

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

Then use that id to fetch the node and change its status

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


来源:https://stackoverflow.com/questions/64604518/unable-to-check-uncheck-the-checkbox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!