web-dev-qa-db-ja.com

VirtualizedSelectでFormik&yupフォーム検証が期待どおりに機能しない

フォームを検証するために、formikでフォームを作成しました。コンポーネントFormik、Form、Field form 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);
_

そして、私はカスタムコンポーネント「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;
_

私のコンポーネントは機能しており、オプションを選択できますが、選択フィールドを空にしたときにエラーが表示される「yup」検証と一緒にformikを選択することができます。

選択フィールドをクリアすると、エラーが発生します-'カテゴリはstringタイプでなければなりませんが、最終値はnullでした。 「null」が空の値として意図されている場合は、スキーマを必ず.nullable() 'としてマークしてください

enter image description here

私のコードは この例 に基づいています。

6
Kamran

フィールドは、validationSchemaに基づいて文字列が必要であることを期待しているようです。

エラーは私を正しい方向に向けるのに役立ちました。 Yup .nullable()のドキュメントは次のとおりです。 https://github.com/jquense/yup#mixednullableisnullable-boolean--true-schema

検証のチェーンに.nullable()を追加してみてください。

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

お役に立てれば。 enter image description here

11
mwarger