Home > database >  React useState not updating all property except when using loops
React useState not updating all property except when using loops

Time:10-30

I am validating form from server side. once I get error message, I wants to show error message on respective textbox field's error message

client side Object

const formFields = {
    firstName: {
        helperText: '',
        error: false
    },
    lastName: {
        helperText: '',
        error: false
    },
    emailID: {
        helperText: '',
        error: false
    },
    phoneNo: {
        helperText: '',
        error: false
    },
    password: {
        helperText: '',
        error: false
    },
    confirmPassword: {
        helperText: '',
        error: false
    }
}

Server side response object after validation

const responseError = errorData.response.data.errors //below object is the response
//{
    //"LastName": ["Enter LastName"],
    //"FirstName": ["Enter FirstName"],
    //"ConfirmPassword": ["Enter Confirm Password","confirm password do not match"]
//}

useState

const [inpValues, setInpValues] = useState(formFields)

Conditions to update

if ClientSideObj.key === responseObj.key then setInpValues of error and helperText field

const responseError = errorData.response.data.errors
console.log(responseError)

var FormFieldName = ""
for (keys in formFields) {
    console.log('FormField keys = '   keys)

    for (var errorKeys in responseError) {
        if (keys.toLowerCase() === errorKeys.toLowerCase()) {

            console.log('* MATCHED FIELDS = '   errorKeys) 
            //Matched 3 fields(LastName,FirstName,ConfirmPassword) successfully

            FormFieldName = keys
            
                    
            setInpValues(prevInpValues => ({
                ...prevInpValues,
                [FormFieldName]: {
                    ...prevInpValues[FormFieldName],
                    error: true,
                    helperText: responseError[errorKeys]
                    }
                })
            )
            console.table(inpValues)
        }
    }
}

Note

I go through this stack overflow already, then I passed previousState values also. still result same.

It's updating only the last for loop condition value

If the response.error object has return only one field, then it's updating that one

CodePudding user response:

What you should do in order to avoid unnecessary extra renders its to loop inside setState callback:

setInpValues(prevInpValues => {

    for (const formKey in formFields) {
     
      for (const errorKey in responseError) {
          if (formKey.toLowerCase() === errorKey.toLowerCase()) {

              prevInpValues[formKey] = {
                ...prevInpValues[formKey],
                error: true,
                helperText: responseError[errorKey]
              }
          }
      }
      return {...prevInpValues}
  }

CodePudding user response:

It's updating only the last for loop condition value

as Miguel Hidalgo states, you should make all changes in one update:

const responseError = errorData.response.data.errors
console.log(responseError)

setInpValues(state => {
  const newState = { ...state };
  for (let errorKey in responseError) {
    for (let formField in formFields) {
      // this would be so much simpler if your properties would be in the correct case and you'd not have to do this dance with `.toLowerCase()`
      if (formField.toLowerCase() !== errorKey.toLowerCase()) {
        continue;
      }

      newState[formField] = {
        ...newState[formField],
        error: true,
        helperText
      }
    }
  }

  return newState
});

If errorKey and fieldName would be identical and you'd not have to match them case insensitive you could write this:

const responseError = errorData.response.data.errors
console.log(responseError)

setInpValues(state => {
  const newState = { ...state };
  for (let formField in responseError) {
    newState[formField] = {
      ...newState[formField],
      error: true,
      helperText: responseError[formField]
    }
  }
  return newState
});
  • Related