javascript Formik & 是的表单验证无法按预期与 VirtualizedSelect 一起使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51222559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:27:25  来源:igfitidea点击:

Formik & yup form validation not working as expected with VirtualizedSelect

javascriptreactjsreact-selectformik

提问by Kamran

I created a form with formik in order to have form validations. I have used the components Formik, Form, Field form formik and configured them:

我用 formik 创建了一个表单以进行表单验证。我使用了 Formik、Form、Field 表单 formik 组件并对其进行了配置:

    import { Formik, Form, Field } from "formik";
    import { object, string } from "yup";
    import isEmpty from "lodash/isEmpty";
    import FormikSelectInput from "../common/FormikSelectInput";

    class App extends Component {
      render() {
        const options = this.props.categories.map(c => {
          return { label: c.name, value: c.name };
        });

        return (
          <Formik
            validationSchema={object().shape({
              category: string().required("Category is required.")
            })}
            initialValues={this.props.obj}
            onSubmit={(values, actions) => {
              console.log(values);
            }}
            render={({ errors, dirty, isSubmitting, setFieldValue }) => (
              <Form>
                <Field
                  name="category"
                  label="Categories"
                  value={this.props.obj.category.name}
                  options={options}
                  component={FormikSelectInput}
                />
                <button
                  type="submit"
                  className="btn btn-default"
                  disabled={isSubmitting || !isEmpty(errors) || !dirty}
                >
                  Save
                </button>
              </Form>
            )}
          />
        );
      }
    }

    //Prop Types validation
    App.propTypes = {
      obj: PropTypes.object.isRequired,
      categories: PropTypes.array.isRequired,
      actions: PropTypes.object.isRequired
    };
    const getElementByID = (items, id) => {
  let res = items.filter(l => l.id === id);
  return res.length ? res[0] : null; //since filter returns an array we need to check for res.length
};
    //Redux connect
    const mapStateToProps = ({ objects, categories }, ownProps) => {
      let obj = {
        id: "",
        name: "",
        category: { id: "", name: "" }
      };
      return {
        obj: getElementByID(objects, ownProps.match.params.id) || obj,
        categories: categories
      };
    };

    export default connect(
      mapStateToProps,
      {...}
    )(App);

And I have a custom component 'FormikSelectInput':

我有一个自定义组件“FormikSelectInput”:

import React, { Component } from "react";
import classnames from "classnames";
import VirtualizedSelect from "react-virtualized-select";
import "react-select/dist/react-select.css";
import "react-virtualized/styles.css";
import "react-virtualized-select/styles.css";

const InputFeedback = ({ children }) => (
  <span className="text-danger">{children}</span>
);

const Label = ({ error, children, ...props }) => {
  return <label {...props}>{children}</label>;
};

class FormikSelectInput extends Component {
  constructor(props) {
    super(props);
    this.state = { selectValue: this.props.value };
  }

  render() {
    const {
      field: { name, ...field }, // { name, value, onChange, onBlur }
      form: { touched, errors }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
      className,
      label,
      ...props
    } = this.props;

    const error = errors[name];
    const touch = touched[name];
    const classes = classnames(
      "form-group",
      {
        "animated shake error": !!error
      },
      className
    );

    console.log("props", props);
    return (
      <div className={classes}>
        <Label htmlFor={name} error={error}>
          {label}
        </Label>
<VirtualizedSelect
          name={name}
          id={name}
          className="form-control"
          {...field}
          {...props}
          onChange={(selectValue) => this.setState(() => {
            this.props.form.setFieldValue('category',selectValue)
            return { selectValue } 
          })}
          value={this.state.selectValue}
        /> 
        {touch && error && <InputFeedback>{error}</InputFeedback>}
      </div>
    );
  }
}

export default FormikSelectInput;

My component is working and I am able to select an option, but why formik together with 'yup' validation showing me an error when I empty the select field.

我的组件正在工作,我可以选择一个选项,但是为什么在我清空选择字段时,formik 与“是的”验证一起显示错误。

When I clear my select field I get an ERROR - 'category must be a stringtype, but the final value was: null. If "null" is intended as an empty value be sure to mark the schema as .nullable()'

当我清除我的选择字段时,我收到一个错误 - 'category must be a stringtype, but the final value is: null。如果将“null”用作空值,请确保将架构标记为.nullable()'

enter image description here

在此处输入图片说明

My code is based on the this example.

我的代码基于这个例子

回答by mwarger

It looks like the field is expecting the string to be required based on your validationSchema.

看起来该字段希望根据您的validationSchema.

The error helped point me in the right direction. Here's the docs for Yup .nullable(): https://github.com/jquense/yup#mixednullableisnullable-boolean--true-schema

该错误帮助我指明了正确的方向。这是 Yup 的文档.nullable()https: //github.com/jquense/yup#mixednullableisnullable-boolean--true-schema

Try adding .nullable() to the chain of validations.

尝试将 .nullable() 添加到验证链中。

validationSchema={object().shape({ category: string().required("Category is required.").nullable() })}

validationSchema={object().shape({ category: string().required("Category is required.").nullable() })}

Hope this helps. enter image description here

希望这可以帮助。 在此处输入图片说明