首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对Material-UI TextField使用YUP

对Material-UI TextField使用YUP
EN

Stack Overflow用户
提问于 2019-07-12 21:31:26
回答 1查看 6K关注 0票数 3

我正在尝试将表单转换为使用Material-ui TextField。我如何让我的YUP验证与此一起工作?下面是我的代码:

代码语言:javascript
运行
复制
import * as React from "react";
import { useState } from 'react';
import { Row, Col } from "react-bootstrap";
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
import axios from "axios";

import Error from "../../Error";

type FormValues = {
  username: string;
  password: string;
  repeatPassword: string;
  fullName: string;
  country: string;
  email: string;
};

export default function CreatePrivateUserForm(props: any) {

  const [errorMessage, setErrorMessage] = useState();

  const createPrivateAccountSchema = Yup.object().shape({
    username: Yup.string()
      .required("Required")
      .min(8, "Too Short!")
      .max(20, "Too Long!")
      .matches(/^[\w-.@ ]+$/, {
        message: "Inccorect carector"
      }),
    password: Yup.string()
      .required("Required")
      .min(10, "Too Short!")
      .max(100, "Too Long!")
      .matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-zA-Z\d\s:]).*$/, {
        message: "Password need to contain 1 uppercase character (A-Z), 1 lowercase character (a-z), 1 digit (0-9) and 1 special character (punctuation)"
      }),
    repeatPassword: Yup.string()
      .required("Required")
      .oneOf([Yup.ref("password")], "Passwords must match")
  });



  function handleSuccess() {
    alert("User was created");
  }

  async function handleSubmit(values: FormValues) {
    const token = await props.googleReCaptchaProps.executeRecaptcha("CreatePrivateUser");

    const headers = {
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        recaptcha: token
      }
    };

    const body = { username: values.username, password: values.password, repeatPassword: values.repeatPassword };

    const url = "xxx";

    try {
      const response = await axios.post(url, body, headers);
      if (response.status === 201) {
        handleSuccess();
      }
      if (response.status === 400) {
        console.log("Bad Request ...");
        setErrorMessage('Bad Request');
      } else if (response.status === 409) {
        console.log("Conflict ...");
        setErrorMessage('Conflict');
      } else if (response.status === 422) {
        console.log("Client Error ...");
        setErrorMessage('Client Error');
      } else if (response.status > 422) {
        console.log("Something went wrong ...");
        setErrorMessage('Something went wrong');
      } else {
        console.log("Server Error ...");
        setErrorMessage('Server Error');
      }
    } catch (e) {
      console.log("Fejl");
    }
  }



  return (
    <React.Fragment>
      <Row>
        <Col xs={12}>
          <p>Please register by entering the required information.</p>
        </Col>
      </Row>
      <Row>
        <Col xs={12}>
          <Formik
            initialValues={{ username: "", password: "", repeatPassword: "" }}
            validationSchema={createPrivateAccountSchema}
            onSubmit={async (values, { setErrors, setSubmitting }) => {
              await handleSubmit(values);
              setSubmitting(false);
            }}>
            {({ isSubmitting }) => (
              <Form>
                {errorMessage ? <Error errorMessage={errorMessage} /> : null}
                <Row>
                  <Col xs={6}>
                    <Row>
                      <Col xs={12}>
                        <TextField
                          label="Username"
                          helperText={touched.username ? errors.username : ""}
                          error={touched.username && Boolean(errors.username)}
                          type="text"
                          name="username"
                          margin="normal"
                          variant="filled"
                        />
                        <ErrorMessage name='username'>{msg => <div className='error'>{msg}</div>}</ErrorMessage>
                      </Col>
                    </Row>
                    <Row>
                      <Col xs={12}>
                        <label htmlFor='password'>Password:</label>
                        <Field type='password' name='password' />
                        <ErrorMessage name='password'>{msg => <div className='error'>{msg}</div>}</ErrorMessage>
                      </Col>
                    </Row>
                    <Row>
                      <Col xs={12}>
                        <label htmlFor='repeatPassword'>Repeat password:</label>
                        <Field type='password' name='repeatPassword' />
                        <ErrorMessage name='repeatPassword'>{msg => <div className='error'>{msg}</div>}</ErrorMessage>
                      </Col>
                    </Row>
                  </Col>
                </Row>
                <Row>
                  <Col xs={12}>
                    <button type='submit' disabled={isSubmitting}>
                      Create User
                      </button>
                  </Col>
                </Row>
              </Form>
            )}
          </Formik>
        </Col>
      </Row>
    </React.Fragment>
  );
}
EN

回答 1

Stack Overflow用户

发布于 2019-08-19 07:41:40

我能看到的第一件事是,您已经剥离了标准的formik <Field />组件,并直接更改为<TextField />。根据<Field />文档的说法,Formik组件实际上是一个特殊的组件,它“将自动地将输入连接到Formik。它使用name属性来匹配Formik状态”。因此,我相信formik实际上不再处理输入,而是不受控制的组件(没有由react state设置值的html组件)。随着formik不再处理输入,内置到formik中的Yup验证以及通过schema prop使用的Yup验证将无法正常工作。

要解决此问题,您可以使用库(material UI建议使用libary - https://github.com/stackworx/formik-material-ui),也可以为formik制作自定义输入组件。这允许您将<Field />的组件属性设置为正确地将material UI与<Field />公开的formik数据连接在一起的组件。

代码语言:javascript
运行
复制
const CustomTextInput = ({
    field, // { name, value, onChange, onBlur }
    form: { touched, errors }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
    ...props
}) => (
    <div>
        <TextField
            error={_.get(touched, field.name) && _.get(errors, field.name) && true}
            helperText={_.get(touched, field.name) && _.get(errors, field.name)}
            {...field}
            {...props}
        />
    </div>
)

然后在您的表单中,您可以这样做

代码语言:javascript
运行
复制
<Field
    name="fieldName"
    component={CustomTextInput}
    label="You can use the Material UI props here to adjust the input"
/>

您可以在field - https://jaredpalmer.com/formik/docs/api/field上的formik文档中找到一个示例和更多信息

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57008018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档