reactjstypescriptvalidationformik

Assigning an error message in Formik validation in TypeScript not working


At this moment I'm trying to build a user input form where a user is supposed to enter a name, email and password, using Formik in React & TypeScript.

Handling inputs itself is working fine, and now I want to add validation functionality to the input form, so I wrote the code like the following.

import { Formik, Form, Field, ErrorMessage } from 'formik'; 

validate(values: User){
    let errors: User; 
    errors = values
    if(!values.password){
      errors.password = 'Enter a password'
    } else if(values.password.length < 8){
      errors.password = 'Enter at least 8 characters for your password'
    }
    console.log("The length of errors.password: " + values.password.length);

    return errors;
  }

return(
      <div>
          <Formik
            initialValues={{ name, email, password }}
            onSubmit={this.onSubmit}
            validate={this.validate}
            enableReinitialize={true}
          >
            {
              (props) => (
                <Form>
                  <fieldset>
                    <label>Name</label>&nbsp;
                    <Field type="text" name="name"/>
                  </fieldset>                                   
                  <fieldset>
                    <label>Email</label>&nbsp;
                    <Field type="text" name="email"/>
                  </fieldset>
                  <ErrorMessage name="password" component="div"/>
                  <fieldset>
                    <label>Password</label>&nbsp;
                    <Field type="password" name="password"/>
                  </fieldset>
                  <button type="submit">Save</button>              
                </Form>
              )
            }      
          </Formik>
      </div>
    )

I wanted to show an error message depending on whether the user has entered a password whose length is long enough, but no error message shows up even when the password is too short.

I added a console.log in the validation method and made sure that the method was invoked. When the password was long enough, like 12 characters long, the part

console.log("The length of errors.password: " + values.password.length);

is invoked and the length of the password is displayed, but when the length becomes shorter than 8, instead of assigning the string 'Enter at least 8 characters for your password' to the errors.password, a warning shows up.

Warning: An unhandled error was caught during low priority validation in <Formik validate /> TypeError: Cannot set property 'password' of undefined

I looked into several GitHub pages and Stack Overflow posts, but haven't found one that seems to be related to my issue.

What am I doing wrong?

The same code was working fine in JavaScript, as my current version is TypeScript maybe there is something that I'm missing?


Solution

  • It looks like undefined is passed as the argument to validate at some point during Formik's internal validation loop. I recommend changing this line:

    let errors: User;
    errors = values; // why are you assigning your error object to the values?
    

    to this:

    let errors: Partial<User> = {};
    

    I'm not sure why you're assigning the current values to your error object. If there are no errors, errors should be an empty object ({}).

    With the new approach, you still get type safety, because you can't assign a property to errors that doesn't exist in the User type:

    errors.password = "Password too short"; // this is fine
    errors.foo = "asdf"; // TypeError - No property "foo" in type "User"