Ant-design: フォームコンポーネントのバリデーター関数に常に `callback()`が必要なのはなぜですか?

作成日 2017年03月03日  ·  38コメント  ·  ソース: ant-design/ant-design

フォームなどの一連のコンポーネントを提供していただきありがとうございます。

問題の説明

フォームの各フィールドは送信前に再度確認する必要があるため、 validateFieldsAndScrollます。しかし、発見は効果がありませんでした。

デバッグ後、指定されたフィールドのセットが関数に渡されると、それが有効になる可能性があることがわかりました。ただし、この一連のファイルに、補助検証の検証ルールでvalidatorの使用を指定するものが含まれている限り、 validateFieldsメソッド全体は有効になりません。

結局、最初に対応するvalidatorコールバックで常にcallback()を返すとは限らなかったことが原因であることがわかりました(それはそれ以上のものだと思います。最初に書き込むことなく、単一の入力に対してそれを行います。通常のチェック)。追加したら大丈夫です。

混乱

すみません、これはバグですか?ドキュメントでは指摘されていないため、 validatorcallback()で返される必要があります。
callbackを返す必要がある場合は、ドキュメントで開発者に通知することをお勧めします。または、デフォルトでデフォルトにすることもできます。

コードセグメント

handleSubmit = (e) => {
        e.preventDefault()

        const { onSubmit } = this.props
        const { validateFieldsAndScroll, getFieldsValue, resetFields } = this.props.form

        validateFieldsAndScroll((err, values) => {
              if (!err) {
                  onSubmit(getFieldsValue())
              }
        })
}
handleConfirmPassword = (rule, value, callback) => {
        const { getFieldValue } = this.props.form
        if (value && value !== getFieldValue('newPassword')) {
            callback('两次输入不一致!')
        }

        // Note: 必须总是返回一个 callback,否则 validateFieldsAndScroll 无法响应
        callback()
 }

render()

<FormItem
    {...formItemLayout}
    label="确认密码"
>
{
    getFieldDecorator('confirmPassword', {
           rules: [{
                  required: true,
                  message: '请再次输入以确认新密码',
            }, {
                  validator: this.handleConfirmPassword
            }],
    })(<Input type="password" />)
}
</FormItem>

環境

  • antdバージョン:最新
  • OSとそのバージョン:OS X
  • ブラウザとそのバージョン:Chrome最新
Usage ❓FAQ 🙅🏻‍♀️ WON'T RESOLVE

最も参考になるコメント

不満がありましたhttps://www.zhihu.com/question/33629737/answer/150154145

オープンソースの原則の1つは、水と地球を隠すことであるという文書を追加できます。

全てのコメント38件

設計によるものです: https

ところで、 callbackを使用して通知しない場合、非同期バリデーターは非同期プロシージャが終了したことをどのように認識しますか?

不満がありましたhttps://www.zhihu.com/question/33629737/answer/150154145

オープンソースの原則の1つは、水と地球を隠すことであるという文書を追加できます。

ドキュメントが更新されました。

こんにちは、この使用法はクラスでのみ書くことができますか?
純粋関数型の方法でReactComponentを記述できますか?もしそうなら、何かケースはありますか?

このAPIデザインは本当にエレガントではありません。特定のチェックボックスが選択されているかどうかを確認したいだけです。

rules: [
            {
              message: 'You need to agree to our terms to sign up.',
              validator: (rule, value, cb) => (value === true ? cb() : cb(true)),
            },
          ],

そして、コールバックに与えられた最初のパラメータはエラーメッセージであり、これもmessageと重複しています(何かが返される限り、 messageが使用されるようですが、カバーする必要がありますmessageエラーメッセージによる)。

ほとんどのユーザーの予想される使用法は、 trueまたはfalseを直接返し、正しいか間違っているかを判断することです。

rules: [
            {
              message: 'You need to agree to our terms to sign up.',
              validator: (rule, value, cb) => value === true,
            },
          ],

利用可能ですが、このAPIを最適化すること、つまりhttps://github.com/yiminghe/async-validator/を使用することをお勧めし

@neekeyは、互換性のあるPRをasync-validatorに送信できます

@neekeyこの奇妙なインターフェースは、次のことを実現します。

  • 非同期検証
  • さまざまなエラーをサポートし、さまざまなメッセージを返します

もっと良い方法はありますか?

<Row>
                <Col span={24} key={"method"}>
                    <FormItem {...formItemMethodLayout} label="请求方法">
                        {getFieldDecorator("method", {
                            initialValue: this.state.data.method,
                            validateTrigger: "onChange",
                            rules: [{
                                required: true,
                                message: `请选择请求方法`
                            }, {
                                //validator: this.state.checkUnique ? this.checkConfirmMethod.bind(this) : (rule, value, callback) => {callback();},
                                validator: (这如何判断当前组件是否开始校验了) ?
 this.checkConfirmMethod.bind(this) : (如果不是当前组件开始校验,就调用其他函数),
                            }]
                        })(
                            <Select placeholder={"请选择请求方法"} onChange={::this.handleChange.bind(this)}>
                                {this.state.apiRequestMethodSelect}
                            </Select>
                        )}
                    </FormItem>
                </Col>
            </Row

機能検証に出会う度に一度見に来ますので覚えにくいです

バリデーター機能

startNumValidator = (rule, value, callback) => {
    const { exportDataCount } = this.props;
    const reg = /^[1-9][0-9]*$/;
    let errors = [];
    if (!reg.test(value) || value > exportDataCount) {
      errors.push(new Error('illegal value'));
    }
    callback(errors);
  }

統一されたコールバックエラーではありませんか?それはかなり合理的だと感じています。
新しいバージョンのantdが非同期検証と同期検証を区別し始めたかどうかわかりませんか?バリデーター(同期)asyncValidator(非同期)

リクエスト後にバックグラウンドで返されたコールバックでこのメッセージプロンプトを呼び出す方法

ルールでバリデーターを使用してカスタム検証を行うときに問題が発生しました
validateFunc =(ルール、値、コールバック)=> {
真であれば) {
console.log(11);
callback( 'エラーメッセージ');
戻る;
}
折り返し電話();
};
検証結果「エラーメッセージ」を対応するFormItemコンポーネントの下に表示したいのですが、コールバックが実行された後、「エラーメッセージ」は対応するFormItemコンポーネントの下に表示されず、コンソールに出力されます。なぜですか?

在对应的FormItem组件下显示のロジックをどのように記述しますか?

@neekeyは、互換性のあるPRをasync-validatorに送信できます

誰かがそれについて言及した、とyimingheは反対した。

在对应的FormItem组件下显示のロジックをどのように記述しますか?

カスタム検証スキームを変更し、onFieldsChange()で判断したところ、カスタムルールが満たされていない場合、エラーが直接変更され、エラー情報がコントロールに表示されます。
onFieldsChange(props, changedFields) { const { dispatch, detail } = props; const finalChangedFields = { ...changedFields }; // 校验时间大小是否符合规则 if ( _.has(changedFields, 'currentDate') && detail?.targetDate && compareCurrentTimeEarlierThanTargetTime( finalChangedFields.currentDate, detail?.targetDate ) ) { finalChangedFields.currentDate.errors = [ { message: 'current Date should be latter than target Date', field: 'currentDate', }, ]; } dispatch({ type: 'controllerModel/saveDetail', payload: { changedFields: finalChangedFields, data: detail, }, }); }

検証に合格しても次のプロンプトが消えないのはなぜですか?

質問してください。このバリデーターは、ページが読み込まれたときに検証を実行できませんか?

@neekey
コールバック機能を

<Form>
          <Form.Item ...>
            {getFieldDecorator('name', {validator: (rule, value, callback) => setTimeout(callback(), 1000)})(
                <Input placeholder="name" />
            )}
          </Form.Item>
....

setTimeoutが発生する前に、コンポーネント全体がアンマウントされます。 次に、タイムアウトが発生し、そのコールバックが発生し、

コンポーネントはsetState (おそらく)を使用するため、次のエラーが発生します。

警告:マウントされていないコンポーネントでReact状態の更新を実行することはできません。 これはノーオペレーションですが、アプリケーションのメモリリークを示しています。 修正するには、componentWillUnmountメソッドのすべてのサブスクリプションと非同期タスクをキャンセルします。

残念ながら、コールバックはキャンセルできません! このエラーを回避する方法はありません!

@jiufengdadi
この問題が発生しました。
私の解決策は、 undefinedcallback渡すことです。 callbackの最初のパラメーターが空の配列の場合、バリデーターは渡されます。 また、パラメータにデフォルト値を設定しているため、 undefinedも機能します。

callback定義: L146

カスタム検証に合格した後にasync-validator:[""]が表示されるのはなぜですか。

チェックが2つある場合、最初のチェックは失敗します。なぜですか。
`` `
ルール:[
{{
必須:true、
メッセージ:「電話番号を入力してください」、
}、
{{
バリデーター:(ルール、値、コールバック)=> {
試す {
if(this.props.form.getFieldValue( 'prefix')== 86 && value){
const reg = / ^ 1d {10} $ /;
if(!reg.test(value)){
新しいError( '何かが間違っています!');をスローします。
}
}
} catch(err){
callback(err);
}
}、
メッセージ:「有効な携帯電話番号を入力してください」、
}、
]、

 rules: [
                {
                  required: true,
                  message: '请输入手机号',
                },
                {
                  validator: (rule, value, callback) => {
                    try {
                      if (this.props.form.getFieldValue('prefix') == 86 && value) {
                        const reg = /^1\d{10}$/;
                        if (!reg.test(value)) {
                          throw new Error('Something wrong!');
                        }
                      }
                    } catch (err) {
                      callback(err);
                       return // +
                    }
                     callback() // +
                  },
                  message: '请输入有效手机号',
                },
              ],

ルールでバリデーターを使用してカスタム検証を行うときに問題が発生しました
validateFunc =(ルール、値、コールバック)=> {
真であれば) {
console.log(11);
callback( 'エラーメッセージ');
戻る;
}
折り返し電話();
};
検証結果「エラーメッセージ」を対応するFormItemコンポーネントの下に表示したいのですが、コールバックが実行された後、「エラーメッセージ」は対応するFormItemコンポーネントの下に表示されず、コンソールに出力されます。なぜですか?

ルールでバリデーターを使用してカスタム検証を行うときに問題が発生しました
validateFunc =(ルール、値、コールバック)=> {
真であれば) {
console.log(11);
callback( 'エラーメッセージ');
戻る;
}
折り返し電話();
};
検証結果「エラーメッセージ」を対応するFormItemコンポーネントの下に表示したいのですが、コールバックが実行された後、「エラーメッセージ」は対応するFormItemコンポーネントの下に表示されず、コンソールに出力されます。なぜですか?

あなたはそれを解決しましたか、同じ状況に遭遇しました

 rules: [
                {
                  required: true,
                  message: '请输入手机号',
                },
                {
                  validator: (rule, value, callback) => {
                    try {
                      if (this.props.form.getFieldValue('prefix') == 86 && value) {
                        const reg = /^1\d{10}$/;
                        if (!reg.test(value)) {
                          throw new Error('Something wrong!');
                        }
                      }
                    } catch (err) {
                      callback(err);
                       return // +
                    }
                     callback() // +
                  },
                  message: '请输入有效手机号',
                },
              ],

メッセージプロンプトは繰り返されますか? 「携帯電話番号を入力してください。有効な携帯電話番号を入力してください」と同様です。

 rules: [
                {
                  required: true,
                  message: '请输入手机号',
                },
                {
                  validator: (rule, value, callback) => {
                    try {
                      if (this.props.form.getFieldValue('prefix') == 86 && value) {
                        const reg = /^1\d{10}$/;
                        if (!reg.test(value)) {
                          throw new Error('Something wrong!');
                        }
                      }
                    } catch (err) {
                      callback(err);
                       return // +
                    }
                     callback() // +
                  },
                  message: '请输入有效手机号',
                },
              ],

メッセージプロンプトは繰り返されますか? 「携帯電話番号を入力してください。有効な携帯電話番号を入力してください」と同様です。

しない

image

次のようにします
image

赤いチェックが消えなかったのはなぜですか? ? ?仕様を満たすこの種の相互影響検証をどのように行うのですか? ? ?

ルールのバリデーターのコールバックは、成功するか失敗するかにかかわらず呼び出す必要があります。違いは、パラメーターが渡されないことです。

ルールでバリデーターを使用してカスタム検証を行うときに問題が発生しました
validateFunc =(ルール、値、コールバック)=> {
真であれば) {
console.log(11);
callback( 'エラーメッセージ');
戻る;
}
折り返し電話();
};
検証結果「エラーメッセージ」を対応するFormItemコンポーネントの下に表示したいのですが、コールバックが実行された後、「エラーメッセージ」は対応するFormItemコンポーネントの下に表示されず、コンソールに出力されます。なぜですか?

ルールでバリデーターを使用してカスタム検証を行うときに問題が発生しました
validateFunc =(ルール、値、コールバック)=> {
真であれば) {
console.log(11);
callback( 'エラーメッセージ');
戻る;
}
折り返し電話();
};
検証結果「エラーメッセージ」を対応するFormItemコンポーネントの下に表示したいのですが、コールバックが実行された後、「エラーメッセージ」は対応するFormItemコンポーネントの下に表示されず、コンソールに出力されます。なぜですか?

あなたはそれを解決しましたか、同じ状況に遭遇しました

私もこの問題に遭遇しました。初期値が空の場合、カスタムバリデーターは通常の入力後のオンブラー時間まで正常にトリガーでき、エラーがある場合はプロンプトが表示されますが、初期初期値に値が設定されると、 validatefieldsは、すべてのフォームコンポーネントの統合検証を実行し、errはnullとして出力され、しばらくすると、検証の失敗が再びコンソールにポップアップ表示されます。カスタムバリデーターは非同期アクションです。

関数内のreturn;を削除して、再試行すると思います。役立つ場合があります。

------------------元のメッセージ------------------
差出人: "Ivan-hl" < [email protected]>;
納期:2019年11月20日(水)17:19
受信者: "ant-design / ant-design" < [email protected]>;
Cc: "wk" < [email protected]>; "Manual" < [email protected]>;
件名:Re:[ant-design / ant-design]フォームコンポーネントのバリデーター関数で常にcallback()が必要なのはなぜですか?フォームのルールでバリデーターを使用するときにメソッド本体が常にcallback()を呼び出す必要があるのはなぜですか?検証?(#5155)

ルールでバリデーターを使用してカスタム検証を行うときに問題が発生しました
validateFunc =(ルール、値、コールバック)=> {
真であれば) {
console.log(11);
callback( 'エラーメッセージ');
戻る;
}
折り返し電話();
};
検証結果「エラーメッセージ」を対応するFormItemコンポーネントの下に表示したいのですが、コールバックが実行された後、「エラーメッセージ」は対応するFormItemコンポーネントの下に表示されず、コンソールに出力されます。なぜですか?

ルールでバリデーターを使用してカスタム検証を行うときに問題が発生しました
validateFunc =(ルール、値、コールバック)=> {
真であれば) {
console.log(11);
callback( 'エラーメッセージ');
戻る;
}
折り返し電話();
};
検証結果「エラーメッセージ」を対応するFormItemコンポーネントの下に表示したいのですが、コールバックが実行された後、「エラーメッセージ」は対応するFormItemコンポーネントの下に表示されず、コンソールに出力されます。なぜですか?

あなたはそれを解決しましたか、同じ状況に遭遇しました

私もこの問題に遭遇しました。初期値が空の場合、カスタムバリデーターは通常の入力後のオンブラー時間まで正常にトリガーでき、エラーがある場合はプロンプトが表示されますが、初期初期値に値が設定されると、 validatefieldsは、すべてのフォームコンポーネントの統合検証を実行し、errはnullとして出力され、しばらくすると、検証の失敗が再びコンソールにポップアップ表示されます。カスタムバリデーターは非同期アクションです。


このスレッドにサブスクライブしているため、これを受け取っています。
このメールに直接返信するか、GitHubで表示するか、登録を解除してください。

残念な

チェック機能に例外がある場合、プロンプトは表示されません。
長い間ピットイン。 。 。

このAntdVは維持されていないのだろうか

@ kongling94

同じ問題に遭遇しました、これ以上のテキストはありませんか?

<a-input id="code" placeholder="请输入用户ID"v-decorator="[ 'code', {rules: [{ required: true, message: '请输入用户ID' }, { validator: handleUsername }], validateTrigger: 'change'} ]" > </a-input>
handleUsername(rule, value, callback) { value = value.trim() if (value.length == 0) { this.username = ''; callback(); } else { fetchUsername({ code: value }) .then((rest) => { if (rest.code == 200) { this.username = rest.data; //callback(); } else { this.username = ''; callback(new Error(rest.msg)) return; } }).finally(() => { callback() }) } },
<a-form :label-col="labelCol" :wrapper-col="wrapperCol" :form="form" @submit="handleSubmit"> <a-button type="primary" htmlType="submit">确定</a-button> </a-form>
クリックして応答とプロンプトがないことを確認し、コンソールにasync-validator:["coderequired"]と入力します
validateFieldsをまったく入力しない
バリデーターとvalidateTriggerを削除し、[OK]をクリックすると、通常どおりプロンプトが表示されます。
何が問題ですか?

<a-input id="code" placeholder="请输入用户ID"v-decorator="[ 'code', {rules: [{ required: true, message: '请输入用户ID' }, { validator: handleUsername }], validateTrigger: 'change'} ]" > </a-input>
handleUsername(rule, value, callback) { value = value.trim() if (value.length == 0) { this.username = ''; callback(); } else { fetchUsername({ code: value }) .then((rest) => { if (rest.code == 200) { this.username = rest.data; //callback(); } else { this.username = ''; callback(new Error(rest.msg)) return; } }).finally(() => { callback() }) } },
<a-form :label-col="labelCol" :wrapper-col="wrapperCol" :form="form" @submit="handleSubmit"> <a-button type="primary" htmlType="submit">确定</a-button> </a-form>
クリックして応答とプロンプトがないことを確認し、コンソールにasync-validator:["coderequired"]と入力します
validateFieldsをまったく入力しない
バリデーターとvalidateTriggerを削除し、[OK]をクリックすると、通常どおりプロンプトが表示されます。
何が問題ですか?

この問題を解決しましたか?この問題も発生しました

<a-input id="code" placeholder="请输入用户ID"v-decorator="[ 'code', {rules: [{ required: true, message: '请输入用户ID' }, { validator: handleUsername }], validateTrigger: 'change'} ]" > </a-input>
handleUsername(rule, value, callback) { value = value.trim() if (value.length == 0) { this.username = ''; callback(); } else { fetchUsername({ code: value }) .then((rest) => { if (rest.code == 200) { this.username = rest.data; //callback(); } else { this.username = ''; callback(new Error(rest.msg)) return; } }).finally(() => { callback() }) } },
<a-form :label-col="labelCol" :wrapper-col="wrapperCol" :form="form" @submit="handleSubmit"> <a-button type="primary" htmlType="submit">确定</a-button> </a-form>
クリックして応答とプロンプトがないことを確認し、コンソールにasync-validator:["coderequired"]と入力します
validateFieldsをまったく入力しない
バリデーターとvalidateTriggerを削除し、[OK]をクリックすると、通常どおりプロンプトが表示されます。
何が問題ですか?

この問題を解決しましたか?この問題も発生しました

// 自定义密码校验
  handleConfirmPassword = (rule, value, callback) => {
    const { getFieldValue } = this.props.form;
    if (value && value !== getFieldValue('newPwd')) {
      callback('两次输入不一致!');
    }

    // Note: 必须总是返回一个 callback,否则 validateFieldsAndScroll 无法响应
    callback();
  };
我是这么解决的

validatorFun(ルール、値、コールバック){
const psw = this.form.getFieldValue( 'newPwd')
if(value && value!== psw){
rule.message = '两次密码不一致'
コールバック(ルール)
}
折り返し電話()
}

このページは役に立ちましたか?
0 / 5 - 0 評価