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
});