State value not updating on form validation

Richard Bridge

Okay so breaking down my code into chunks I have the following in HTML:

<input
    type="text"
    name="email"
    id="email"
    autoComplete="email"
    onChange={(e) => {validateField(e.target)}}
    className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
/>
<FormFieldError
    Field='email'
    FormFieldErrors={formFieldErrors}
    />

The validateField function looks like this:

const validateField = (field) => {
// console.log('validatefield', field.id, field.value)
switch(field.id) {
    case 'email':
        const pattern = /[a-zA-Z0-9]+[\.]?([a-zA-Z0-9]+)?[\@][a-z]{3,9}[\.][a-z]{2,5}/g
        const result = pattern.test(field.value)
        if (result !== true) {
            setFormFieldErrors({...formFieldErrors, email: 'Please enter a valid email address'})
            console.log('Please enter a valid email address')
        } else {
            setFormFieldErrors({...formFieldErrors, email: null})
        }
        break

}

}

The FormFieldError function looks like this:

function FormFieldError({ Field, FormFieldErrors }) {
let message = FormFieldErrors[Field] ? FormFieldErrors[Field] : null
return (
    <>
        <div className="text-red-500 text-xs text-bold">{(message)}</div>
    </>
)

}

Now, when in the onSubmit of the form I got to the following function:

const submitNewRegistration = async (event) => {
    event.preventDefault()

    Array.prototype.forEach.call(event.target.elements, (element) => {
        validateField(element);
    })

    let errors = Object.keys(formFieldErrors).some(key => key !== null)
    console.log(errors)

}

I am declaring formFieldErrors in my state like this: const [formFieldErrors, setFormFieldErrors] = useState({})

When I am changing a field the onChange function works perfectly for each input, and if the input is wrong then the message below the input shows up thanks to the formFieldErrors displays the message underneath the input. However, when I call validateInput from my submitNewRegistration function, setFormFieldErrors doesnt seem to be called. In fact, even if I put setFormFieldErrors in to submitNewRegistration it doesnt seem to change the state of formFieldErrors. So when I am trying to validate the form just before submitting it I do not get any errors.

Can anyone explain to me why its working with the onChange method and now when I call it from submitNewRegistration ??

DannyMoshe

It's not that setFormFieldErrors isn't called, the issue is you are trying to rely on the state value before the state has been updated. When you call setState the state doesn't update immediately. This is because setState is asynchronous, essentially a promise which resolves upon the next render of your component.

So to solve this, you need to strip your validation logic outside of the state update. In other words:

const validateField = (field) => {
// console.log('validatefield', field.id, field.value)
 switch(field.id) {
    case 'email':
        const pattern = /[a-zA-Z0-9]+[\.]?([a-zA-Z0-9]+)?[\@][a-z]{3,9}[\.][a-z]{2,5}/g
        const result = pattern.test(field.value)
        if (result !== true) {
            return {email: 'Please enter a valid email address'}
            console.log('Please enter a valid email address')
        } else {
            return {email: null}
        }
        break



 }

Then in your html:

<input
    type="text"
    name="email"
    id="email"
    autoComplete="email"
    onChange={(e) => {
      setFormFieldErrors({...formFieldErrors, ...validateField(e.target)})
    }
    className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
/>
<FormFieldError
    Field='email'
    FormFieldErrors={formFieldErrors}
    />

And finally in the submit:

const submitNewRegistration = async (event) => {
    event.preventDefault()
    let formErrors = formFieldErrors;;
    Array.prototype.forEach.call(event.target.elements, (element) => {
        formErrors = {...formErrors, ...validateField(element)};
    })
    setFormFieldErrors(formErrors)
    let errors = Object.keys(formErrors).some(key => key !== null)
    console.log(errors)

}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Consistent updating of validation state in a custom reactive form control?

Updating state with form inputs

FormControl not updating state pristine/dirty or value after making changes to form

MudBlazor Async Validation Not Updating State

updating state through form inputs

Redux Form - initialValues not updating with state

React Form not updating state onChange

State validation in a JavaScript registration form

React, state setter not updating the value

Updating a value in a React state array

Set state method not updating the value

Form not updating values , validation fails but no errors

Antd 3.26 form validation messages are not rerendering with new value when state/props are changing

AngularJS form validation : $dirty value change through ui.router state changes

Updating state on props change in React Form

Updating comments and state from the same form

Angular custom form control not updating form value

Bootstrap 4, is-pending form validation state

Reactive form validation: unable to change state to valid

ReactJS form validation when state is not immediately updated

While doing form validation on submit a form, the component is not updating in React

Symfony form validation value is in array

(React Hooks) Ref method not updating state value

React updating the state value in a wrong place

updating one value in State array react native

State value not updating when passed as route prop

input value not updating when mutating state

State not updating as a plain value, but updates as a function

React class component state value not updating

TOP Ranking

HotTag

Archive