Реагировать. Проверка формы

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть многоступенчатая форма для регистрации. Какой самый простой и наилучший подход для проверки формы? Что я должен использовать? Можно ли использовать Formik для этого? Не могли бы вы подсказать мне, что делать? Вот одна из форм:

 return(
<Container>
  <Row className="justify-content-center">
    <Col md="8">
      <Card border="dark">
        <Card.Title className="text-center">New User</Card.Title>
        <Card.Body>
          <Form>
            <Form.Group controlId="formGridFirstName">
              <Form.Label>First Name</Form.Label>
              <Form.Control type="text" value={formValues.firstName} onChange={handleChange('firstName')} />
            </Form.Group>

            <Form.Group controlID="formGridLastName">
              <Form.Label>Last Name</Form.Label>
              <Form.Control type="text" value={formValues.lastName} onChange={handleChange('lastName')} />
            </Form.Group>

            <Form.Group controlID="formGridEmail">
              <Form.Label>Email</Form.Label>
              <Form.Control type="email" value={formValues.email}  onChange={handleChange('email')} />
            </Form.Group>

            <Form.Group controlId="formGridPassword">
              <Form.Label>Password</Form.Label>
              <Form.Control type="password" value={formValues.password}  onChange={handleChange('password')} />
            </Form.Group>

            <Form.Group controlId="formGridPhone">
              <Form.Label>Phone</Form.Label>
              <Form.Control type="tel" value={formValues.phone} onChange={handleChange('phone')} />
            </Form.Group>

            <Button variant="light" type="submit" size="lg" onClick={redirectToHome}>Cancel</Button>
            <Button variant="primary" type="submit" size="lg" onClick={saveAndContinue}>Next</Button>
          </Form>
        </Card.Body>
      </Card>
    </Col>
  </Row>
</Container>
 

);
};

Ответ №1:

Вы можете использовать Formik и Yup для схемы проверки:

https://formik.org/docs/api/formik#validationschema-schema—-schema

ссылки npm:

https://www.npmjs.com/package/formik

https://www.npmjs.com/package/yup

Это будет выглядеть так:

 export default function MyForm() {
  const initValues = {
    firstName: "",
    lastName: "",
    email: "",
    password: "",
    phone: ""
  };
  const schema = Yup.object().shape({
    firstName: Yup.string(),
    lastName: Yup.string(),
    email: Yup.string().email("Email format is invalid."),
    password: Yup.string()
      .required("No password provided.")
      .min(8, "Password is too short - should be 8 chars minimum.")
      .matches(/[a-zA-Z]/, "Password can only contain Latin letters."),
    phone: Yup.string().phone(" ")
  });

  return (
    <Formik validationSchema={schema} initialValues={initValues}>
      {props => {
        const {
          values,
          touched,
          errors,
          isSubmitting,
          handleChange,
          setFieldTouched
        } = props;
        return (
          <Container>
            <Row className="justify-content-center">
              <Col md="8">
                <Card border="dark">
                  <Card.Title className="text-center">New User</Card.Title>
                  <Card.Body>
                    <Form>
                      <Form.Group controlId="formGridFirstName">
                        <Form.Label>First Name</Form.Label>
                        <Form.Control
                          name="firstName"
                          type="text"
                          value={values.firstName}
                          onChange={handleChange}
                          setFieldTouched={setFieldTouched}
                          errors={errors}
                        />
                      </Form.Group>

                      <Form.Group controlID="formGridLastName">
                        <Form.Label>Last Name</Form.Label>
                        <Form.Control
                          name="lastName"
                          type="text"
                          value={values.lastName}
                          onChange={handleChange}
                          setFieldTouched={setFieldTouched}
                          errors={errors}
                        />
                      </Form.Group>

                      <Form.Group controlID="formGridEmail">
                        <Form.Label>Email</Form.Label>
                        <Form.Control
                          name="email"
                          type="email"
                          value={values.email}
                          onChange={handleChange}
                          setFieldTouched={setFieldTouched}
                          errors={errors}
                        />
                      </Form.Group>

                      <Form.Group controlId="formGridPassword">
                        <Form.Label>Password</Form.Label>
                        <Form.Control
                          name="password"
                          type="password"
                          value={values.password}
                          onChange={handleChange}
                          setFieldTouched={setFieldTouched}
                          errors={errors}
                        />
                      </Form.Group>

                      <Form.Group controlId="formGridPhone">
                        <Form.Label>Phone</Form.Label>
                        <Form.Control
                          name="phone"
                          type="tel"
                          value={values.phone}
                          onChange={handleChange}
                          setFieldTouched={setFieldTouched}
                          errors={errors}
                        />
                      </Form.Group>

                      <Button
                        variant="light"
                        type="submit"
                        size="lg"
                        onClick={redirectToHome}
                      >
                        Cancel
                      </Button>
                      <Button
                        variant="primary"
                        type="submit"
                        size="lg"
                        onClick={saveAndContinue}
                      >
                        Next
                      </Button>
                    </Form>
                  </Card.Body>
                </Card>
              </Col>
            </Row>
          </Container>
        );
      }}
    </Formik>
  );
}
 

Но вам также следует изменить свой Form.Control компонент:

Добавить

 import { ErrorMessage, getIn } from "formik";
const error = getIn(props.errors, props.name);
 

и добавьте к вашему вводу эти атрибуты

 onChange={(e) => {setFieldTouched("firstName");handleChange(e);}
error={error}
 

и ошибка, чтобы показать

 <Error component="div" name={props.name} />
 

Комментарии:

1. Спасибо! Я уже это делаю. Нужны ли мне initValues? Я сохраняю значения формы в состоянии.

Ответ №2:

Я бы предложил добавить ваши собственные валидаторы и объединить входные данные одного типа. Например, имя и фамилия являются строками, поэтому у вас может быть средство проверки для строковых типов. Вы могли бы сделать это так

 //validator.js

const stringValidator = (value) => {
   if(isEmpty(value)){
     return { isValid: false, errors: ["Field cannot be blank"] }
   } 
   return { isValid: true, errors: [] } 
}

const config = {
   firstName: stringValidator,
   lastName: stringValidator,
   email: emailValidator,
   cellphone: cellphoneValidator,
   password: passwordValidator
}

const getValidator = (questionId) => config[questionId];

export default (questionId, value) => {
   const validate = getValidator(questionId);
   return validate(value)
}

...
// Form.js class

answerQuestion(questionId){
   return (e) => {
     const answer = e.target.value;
     const validation = validate(questionId, answer)
     const { errors } = validation;
     let { fields } = this.state;
     fields[questionId] = { errors, value, label: field.label }
     this.setState({ fields })
   }
}

...

<Form>
   {this.state.fields.map( field => {
     return( 
         <Form.Group>
          <Form.Label>{field.label}</Form.Label>
          <Form.Control type="text" value={field.value} onChange={this.answerQuestion(field.questionId)} />
          {field.errors.map(err => <span>{err}</span>} 
        </Form.Group>
     )
   }
</Form>