使用Formik编辑条目,Yup无法识别现有字段

如何解决使用Formik编辑条目,Yup无法识别现有字段

当我创建实体(在这种情况下为公司)时,我使用FormikYup来检查字段是否正确以及是否全部引入(全部为必填项)。

当我创建一个实体时,它可以很好地工作:只有在所有字段都被引入并且满足规则的情况下,您才可以创建它(电子邮件中目前只有一个规则)。

这是用于创建具有两个字段名称和电子邮件的新公司的代码

    import React from 'react';
    import { Redirect } from 'react-router-dom';
    import { Formik,Form,Field } from 'formik';
    import { Input,Button,Label,Grid } from 'semantic-ui-react';
    import { connect } from 'react-redux';
    import * as Yup from 'yup';
    import { Creators } from '../../../actions';
    import Layout from '../../Layout/Layout';
    
    class CreateCompanyForm extends React.PureComponent {
      constructor(props) {
        super(props);
    
        this.state = {
          name: '',contactMail: '',redirectCreate: false,redirectEdit: false,edit: false,};
      }
    
      componentDidMount() {
        const {
          getCompany,location: { pathname },} = this.props;
      }
    
      handleSubmit = values => {
        const { createCompany,getCompanies } = this.props;
        createCompany(values);
        this.setState({ redirectCreate: true });
        getCompanies(this.props.query);
      };
    
      render() {
        let title = 'Create Company';
        let buttonName = 'Create';
        let submit = this.handleSubmitCreate;
    
        const { redirectCreate,redirectEdit } = this.state;
    
        if (redirectCreate) {
          return <Redirect to="/companies" />;
        }
        const initialValues = {
          name: '',};
        const requiredErrorMessage = 'This field is required';
        const emailErrorMessage = 'Please enter a valid email address';
        const validationSchema = Yup.object({
          name: Yup.string().required(requiredErrorMessage),contactMail: Yup.string()
            .email(emailErrorMessage)
            .required(requiredErrorMessage),});
        return (
          <Layout>
            <div>
              <Button type="submit" form="amazing">
                Create company
              </Button>
              <Button onClick={() => this.props.history.goBack()}>discard</Button>
              <div>Create company</div>
            </div>
    
            <Formik
              htmlFor="amazing"
              initialValues={initialValues}
              validationSchema={validationSchema}
              onSubmit={values => this.handleSubmit(values)}>
              {({ values,errors,touched,setValues }) => (
                <Form id="amazing">
                  <Grid columns={2}>
                    <Grid.Column>
                      <Label>Company Name</Label>
                      <Field name="name" as={Input} placeholder="Hello" />
                      <div>{touched.name && errors.name ? errors.name : null}</div>
                    </Grid.Column>
    
                    <Grid.Column>
                      <Label>Contact Mail</Label>
                      <Field
                        name="contactMail"
                        as={Input}
                        placeholder="johnappleseed@hello.com"
                      />
                      <div>
                        {touched.contactMail && errors.contactMail
                          ? errors.contactMail
                          : null}
                      </div>
                    </Grid.Column>
                  </Grid>
                </Form>
              )}
            </Formik>
          </Layout>
        );
      }
    }
    
    const mapStatetoProps = state => ({
      companies: state.companies.companies,company: state.companies.selectedCompany,query: state.companies.query,});
    
    const mapdispatchToProps = {
      getCompanies: Creators.getCompaniesRequest,createCompany: Creators.createCompanyRequest,getCompany: Creators.getCompanyRequest,updateCompany: Creators.updateCompanyRequest,};

export default connect(mapStatetoProps,mapdispatchToProps)(CreateCompanyForm);

当我要编辑公司时出现问题。因此,当某人在“编辑”按钮上单击公司时,应打开公司,其所有字段都包含应编辑的当前值。

获取这些当前值,我正在使用状态,例如可以从this.state.email访问电子邮件,并且为了更改其值,添加onChange方法

可以在文本输入中修改值。但是,它触发Yup消息,提示即使该字段中有数据,该字段也是必需的-为什么会发生这种情况?该字段不为空,这是必须显示该消息的情况。

当然,当我单击以保存它时,它不会更新该实体,因为它需要这些字段。

代码如下:

import React from 'react';
...

class CreateCompanyForm extends React.PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      name: '',};
  }

  componentDidMount() {
    const {
      getCompany,} = this.props;
    if (pathname.substring(11) !== 'create') { // checks the URL if it is in edit mode 
      getCompany(pathname.substring(16));
      this.setState({
        edit: true,});
      this.setState({
        name: this.props.company.name,contactMail: this.props.company.contactMail,});
    }
  }

    onChange = (e,{ name,value }) => { // method to update the state with modified value in input
      this.setState({ [name]: value });
    };

  handleSubmit = values => {
    const { createCompany,getCompanies } = this.props;
    createCompany(values);
    this.setState({ redirectCreate: true });
    getCompanies(this.props.query);
  };

    handleSubmitEdit = e => {
      e.preventDefault();
      const { name,contactMail } = this.state;
      const { updateCompany } = this.props;
      updateCompany(this.props.company._id,{
        name,contactMail,});
      this.setState({ redirectEdit: true });
    };

  render() {
    let title = 'Create Company';
    let buttonName = 'Create';
    let submit = this.handleSubmitCreate;

    const { redirectCreate,redirectEdit } = this.state;

    if (redirectCreate) {
      return <Redirect to="/companies" />;
    }

    if (redirectEdit) {
      return <Redirect to={`/companies/${this.props.company._id}`} />;
    }

    if (this.state.edit) {
      title = 'Edit Company';
      buttonName = 'Edit';
      submit = this.handleSubmitEdit;
    }

    const initialValues = {
      name: '',};
    const requiredErrorMessage = 'This field is required';
    const emailErrorMessage = 'Please enter a valid email address';
    const validationSchema = Yup.object({
      name: Yup.string().required(requiredErrorMessage),contactMail: Yup.string()
        .email(emailErrorMessage)
        .required(requiredErrorMessage),});
    return (
      <Layout>
        <div>
          <Button type="submit" form="amazing">
            Create company
          </Button>
          <Button onClick={() => this.props.history.goBack()}>discard</Button>
          <div>Create company</div>
        </div>

        <Formik
          htmlFor="amazing"
          initialValues={initialValues}
          validationSchema={validationSchema}
          onSubmit={values => this.handleSubmit(values)}>
          {({ values,setValues }) => (
            <Form id="amazing">
              <Grid columns={2}>
                <Grid.Column>
                  <Label>Company Name</Label>
                  <Field
                    name="name"
                    as={Input}
                    placeholder="Hello"
                    value={this.state.name || ''} // takes the value from the state
                    onChange={this.onChange} // does the changing 
                  />
                  <div>{touched.name && errors.name ? errors.name : null}</div>
                </Grid.Column>

                <Grid.Column>
                  <Label>Contact Mail</Label>
                  <Field
                    name="contactMail"
                    as={Input}
                    placeholder="johnappleseed@hello.com"
                    value={this.state.contactMail || ''} // takes the value from the state
                    onChange={this.contactMail} // does the changing 
                  />
                  <div>
                    {touched.contactMail && errors.contactMail
                      ? errors.contactMail
                      : null}
                  </div>
                </Grid.Column>
              </Grid>
            </Form>
          )}
        </Formik>
      </Layout>
    );
  }
}

...

export default connect(mapStatetoProps,mapdispatchToProps)(CreateCompanyForm);

关于如何解决该问题并使字段可编辑并在字段中已有数据时删除'This field is required'消息的任何想法?

解决方法

您需要做3个小改动:

1。您的初始值始终设置为:

const initialValues = {
   name: '',contactMail: '',};

您需要将其更改为:

const initialValues = {
   name: this.state.name,contactMail: this.state.contactMail,};

2。将enableReinitialize添加到Formik

即使更改为nº1,您的提交仍会引发错误,这是因为在创建组件时,Formik会使用构造函数中的值进行渲染:

this.state = {
      name: "",contactMail: "",redirectCreate: false,redirectEdit: false,edit: false,};

并且在componentDidMount中更改状态时,Formik不会使用更新值重新初始化:

componentDidMount() {
    const {
      getCompany,location: { pathname },} = this.props;
    if (pathname.substring(11) !== 'create') { // checks the URL if it is in edit mode 
      getCompany(pathname.substring(16));
      this.setState({
        edit: true,});
      this.setState({
        name: this.props.company.name,contactMail: this.props.company.contactMail,});
    }
  }

因此,要重新初始化Formik,您需要向其添加enableReinitialize,如下所示:

  <Formik
     htmlFor="amazing"
     /// HERE'S THE CODE
     enableReinitialize
     initialValues={initialValues}
     ....

3。使用enableReinitializeFormik将触发“模糊”和“更改”的验证。为避免这种情况,您可以将validateOnChangevalidateOnBlur添加为false:

 <Formik
   htmlFor="amazing"
   enableReinitialize
   validateOnChange={false}
   validateOnBlur={false}
   initialValues={initialValues}
   .....

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?