web-dev-qa-db-ja.com

Yupの条件付き検証

チェックボックスが選択されている場合にのみ表示される電子メールフィールドがあります(ブール値はtrueです)。フォームが送信されると、チェックボックスがオンになっている場合(booleanがtrue)に、このフィールドに必要なものだけを入力します。

これは私がこれまでに試したことです:

_    const validationSchema = yup.object().shape({
       email: yup
             .string()
             .email()
             .label('Email')
             .when('showEmail', {
                 is: true,
                 then: yup.string().required('Must enter email address'),
             }),
        })
_

他にもいくつかのバリエーションを試しましたが、FormikとYupからエラーが発生します。

Uncaught (in promise) TypeError: Cannot read property 'length' of undefined at yupToFormErrors (formik.es6.js:6198) at formik.es6.js:5933 at <anonymous> yupToFormErrors @ formik.es6.js:6198

そして、私もYupから検証エラーを受け取ります。何が間違っていますか?

18
reectrix

showEmailフィールドの検証ルールを定義していない可能性があります。

CodeSandoxを実行してテストし、追加したらすぐに:

showEmail: yup.boolean()

フォームは検証を正しく開始し、エラーはスローされませんでした。

これはURLです: https://codesandbox.io/s/74z4px0k8q

そして、将来のためにこれは正しい検証スキーマでした:

validationSchema={yup.object().shape({
    showEmail: yup.boolean(),
    email: yup
      .string()
      .email()
      .when("showEmail", {
        is: true,
        then: yup.string().required("Must enter email address")
      })
  })
}
28
João Cunha

@JoãoCunhaの答えに完全に同意します。ラジオボタンの使用例の補足です。

ラジオボタンを条件として使用すると、ブール値の代わりに文字列の値を確認できます。例えばis: 'Phone'

const ValidationSchema = Yup.object().shape({
  // This is the radio button.
  preferredContact: Yup.string()
    .required('Preferred contact is required.'),
  // This is the input field.
  contactPhone: Yup.string()
    .when('preferredContact', {
      is: 'Phone',
      then: Yup.string()
        .required('Phone number is required.'),
    }),
  // This is another input field.
  contactEmail: Yup.string()
    .when('preferredContact', {
      is: 'Email',
      then: Yup.string()
        .email('Please use a valid email address.')
        .required('Email address is required.'),
    }),

});

これは、ReactJSのonChangeメソッドで記述されたラジオボタンが、条件チェックをトリガーするキーです。

<label>
  <input
    name="preferredContact" type="radio" value="Email"
    checked={this.state.preferredContact == 'Email'}
    onChange={() => this.handleRadioButtonChange('Email', setFieldValue)}
  />
  Email
</label>
<label>
  <input
    name="preferredContact" type="radio" value="Phone"
    checked={this.state.preferredContact == 'Phone'}
    onChange={() => this.handleRadioButtonChange('Phone', setFieldValue)}
  />
  Phone
</label>

ラジオボタンが変更されたときのコールバック関数を次に示します。 Formikを使用している場合、 setFieldValue が最適です。

handleRadioButtonChange(value, setFieldValue) {
  this.setState({'preferredContact': value});
  setFieldValue('preferredContact', value);
}
4
Eric Tan