ProMaker Dev
ProMaker Dev

Reputation: 155

react setstate does not work properly on loops

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

Answers (2)

Bhojendra Rauniyar
Bhojendra Rauniyar

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

Awais Rafiq Chaudhry
Awais Rafiq Chaudhry

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

Related Questions