【问题标题】:React useEffect not rerendering反应useEffect不重新渲染
【发布时间】:2020-06-25 05:03:15
【问题描述】:
我正在尝试更改数组中的值并使用 useEffect 重新渲染组件,但 useEffect 未触发。值正在更改,但调用 useState 无效。
const handleOptionClick = (e) => {
var el = document.getElementById(e.currentTarget.id);
var tar = el.getAttribute("data");
var ans = awnsers;
ans.map((res) => {
if (res.Awnser === tar) {
res.IsChecked = !res.IsChecked;
return true;
}
return true;
});
setAwnsers(ans);
}
和
useEffect(() => {
console.log(awnsers);
},[awnsers])
【问题讨论】:
标签:
reactjs
react-hooks
use-effect
【解决方案1】:
由于您在ans 上执行map,因此我认为它是一个数组。数组是通过引用复制的。因此,为了响应重新渲染awnsers,您必须创建一个新数组。
var ans = [...awnsers]; // or JSON.parse(JSON.stringify(awnsers)) for deep clone
ans.map((res) => {
if (res.Awnser === tar) {
res.IsChecked = !res.IsChecked;
return true;
}
return true;
});
setAwnsers(ans);
Awnsers 也是错字吗?你是说Answers吗?
【解决方案2】:
你不会保存你保存在状态中的 array::map 函数的结果,所以基本上awnsers 数组中的状态引用值不会改变,组件也不会重新渲染。
const handleOptionClick = (e) => {
var el = document.getElementById(e.currentTarget.id);
var tar = el.getAttribute("data");
setAwnsers(prevAwnser => prevAwnser.map(res => ({
...res,
IsChecked: res.Awnser === tar ? !res.IsChecked : res.IsChecked,
})));
}
【解决方案3】:
React 在更新状态时执行 Object.is 比较,如果先前和当前状态的引用相同,则检查失败并且不会触发重新渲染
同样 map 返回数组的新引用,你不能改变原始数组,而是以不可变的方式更新它
const handleOptionClick = (e) => {
var el = document.getElementById(e.currentTarget.id);
var tar = el.getAttribute("data");
var ans = awnsers; // Check for typo
ans = ans.map((res) => {
if (res.Awnser === tar) {
{...res, IsChecked:!res.IsChecked};
}
return res;
});
setAwnsers(ans);
}
附:您还可以使用功能 setState 方法来更新状态,因为您正在根据以前的值更新当前状态
const handleOptionClick = (e) => {
var el = document.getElementById(e.currentTarget.id);
var tar = el.getAttribute("data");
setAwnsers(prevAns => ans.map((res) => {
if (res.Awnser === tar) {
{...res, IsChecked:!res.IsChecked};
}
return res;
}));
}