我有以下组件,其状态跟踪复选框:
import { useState } from "react";
function SideBar() {
const [queryObject, setQueryObject] = useState({
genders: [],
availabilities: []
});
function handleChange(event) {
const { name, checked } = event.target;
if (name === "male" || name === "female") {
if (checked) {
setQueryObject((prevQueryObject) => {
prevQueryObject.genders.push(name);
return prevQueryObject;
});
} else {
setQueryObject((prevQueryObject) => {
return prevQueryObject.genders.filter((e) => e !== name);
});
}
return;
}
if (name === "available" || name === "not available") {
if (checked) {
setQueryObject((prevQueryObject) => {
prevQueryObject.availabilities.push(name);
return prevQueryObject;
});
} else {
setQueryObject((prevQueryObject) => {
return prevQueryObject.availabilities.filter((e) => e !== name);
});
}
return;
}
}
return (
<div>
<input
type="checkbox"
checked={queryObject.genders.includes("male")}
onChange={handleChange}
name="male"
/>
<span>Male</span>
<input
type="checkbox"
checked={queryObject.genders.includes("female")}
onChange={handleChange}
name="female"
/>
<span>Female</span>
<br />
<input
type="checkbox"
checked={queryObject.availabilities.includes("available")}
onChange={handleChange}
name="available"
/>
<span>Available</span>
<input
type="checkbox"
checked={queryObject.availabilities.includes("not available")}
onChange={handleChange}
name="not available"
/>
<span>Not available</span>
</div>
);
}
export default SideBar;
当我试图点击复选框它不立即更新,我发现,每当我保存我的文本文件再次浏览器重新加载,然后它更新,我认为问题是在我的handleChange函数,是我处理setQueryObject错误的方式吗?
问题在于更新queryObject
状态的方法。因为queryObject
状态是一个对象,如果我们尝试直接修改对象像这样:-
setQueryObject((prevQueryObject) => {
prevQueryObject.genders.push(name);
return prevQueryObject;
});
React不识别状态中的任何变化,因为对象具有相同的引用,所以它不会更新DOM
。因此,我们需要创建该对象的deep copy
并将其设置回object state
,以便识别对象状态的变化并使React更新DOM。
setQueryObject((prevQueryObject) => {
return{...prevQueryObject,genders:[...prevQueryObject.genders,name]};
});
完整的工作代码在这里- CodeSandbox Link
感谢Yury,我重写了代码,它可以工作了
import { useState } from "react";
function SideBar() {
const [queryObject, setQueryObject] = useState({
genders: [],
availabilities: []
});
function handleChange(event) {
const { name, checked } = event.target;
if (name === "male" || name === "female") {
if (checked) {
setQueryObject((prevQueryObject) => {
return {
...prevQueryObject,
genders: prevQueryObject.genders.concat(name)
};
});
} else {
setQueryObject((prevQueryObject) => {
return {
...prevQueryObject,
genders: prevQueryObject.genders.filter((e) => e !== name)
}
});
}
return;
}
if (name === "available" || name === "not available") {
if (checked) {
setQueryObject((prevQueryObject) => {
return {
...prevQueryObject,
availabilities: prevQueryObject.availabilities.concat(name)
};
});
} else {
setQueryObject((prevQueryObject) => {
return {
...prevQueryObject,
availabilities: prevQueryObject.availabilities.filter(
(e) => e !== name
)
};
});
}
return;
}
}
return (
<div>
<input
type="checkbox"
checked={queryObject.genders.includes("male")}
onChange={handleChange}
name="male"
/>
<span>Male</span>
<input
type="checkbox"
checked={queryObject.genders.includes("female")}
onChange={handleChange}
name="female"
/>
<span>Female</span>
<br />
<input
type="checkbox"
checked={queryObject.availabilities.includes("available")}
onChange={handleChange}
name="available"
/>
<span>Available</span>
<input
type="checkbox"
checked={queryObject.availabilities.includes("not available")}
onChange={handleChange}
name="not available"
/>
<span>Not available</span>
</div>
);
}
export default SideBar;