Reputation: 155
i am getting a validation response from my backend as an array like this
[
{ param: "secondName", msg: "second name is required" },
{ param: "password", msg: "password is required" }
]
and i have a state in my react component like this
const [errs, setErrs] = useState({
firstName: null,
secondName: null,
password: null,
email: null,
})
goal is to change in my state only the fields mentioned in my response.params
on form submit and leave out the rest as they are null
.
this is what i tried:
const submitFoo = () => {
console.log(localErrs) //all props are set to null (default)
res.forEach((single) => {
setLocalErrs({
...localErrs,
[single.param]: single.msg
});
});
console.log(localErrs);//only password is set to the `response.msg`, instead of `password` AND `secondName`
};
but the issue is it's only changing the last item in my "errs state"; output is:
{
first: null,
second: null,
password: 'password is required',
email: null,
}
ps: i tried it with vanilla js by looping through the array and setting Errs obj's props directly to the response.msg and it worked. so proplem must be with react setstate
Upvotes: 1
Views: 2615
Reputation: 85545
Avoid updating state in a loop. Update state like:
let errObj = {}
res.forEach((single) => {
errObj[single.param] = single.msg
})
setLocalErrs({
...localErrs,
...errObj
})
By the way, you can simply use:
setLocalErrs(errObj)
Since errObj
has all updated states value.
Upvotes: 2
Reputation: 490
Try using the Fat Arrow approach to set state as follows:
setLocalErrs(localErrs => ({ ...localErrs, [single.param]: single.msg }));
It avoids state loss in case setter function is called twice at the same time due to different async calls, etc.
Upvotes: 4