无法 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]}
/>
我正在制作一个 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]}
/>