Reputation: 1183
I am trying to change a value in an array and rerender the component with useEffect but useEffect is not triggering. Value is being changed but calling useState has no effect.
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);
}
and
useEffect(() => {
console.log(awnsers);
},[awnsers])
Upvotes: 1
Views: 2121
Reputation: 281774
React performs an Object.is comparison while updating state and if the reference of previous and current state is same the check fails and a re-render is not triggered
Also map returns a new reference of the array and you must not mutate the original array but update it in an immutable manner
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);
}
P.S. You can also make use of functional setState approach to update state since you are updating current state based on previous values
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;
}));
}
Upvotes: 0
Reputation: 202874
You don't save the result of the array::map function that you save in state, so essentially the state reference values in the awnsers
array don't change and the component won't re-render.
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,
})));
}
Upvotes: 0
Reputation: 3526
Since you are doing a map
on ans
, I take it to be an array. Arrays are copied by reference. So for react to re-render the awnsers
, you will have to create a new array.
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);
Also is Awnsers
a typo? Did you mean Answers
?
Upvotes: 1