Ant-design: por que sempre precisamos de `callback ()` na função validadora no componente Form?

Criado em 3 mar. 2017  ·  38Comentários  ·  Fonte: ant-design/ant-design

Obrigado por fornecer uma série de componentes como o Form.

Descrição do Problema

Como cada campo do formulário precisa ser verificado novamente antes do envio, validateFieldsAndScroll . Mas a descoberta não surtiu efeito.

Após a depuração, descobriu-se que se um conjunto de campos especificados for passado para a função, ele pode ter efeito. Mas enquanto este conjunto de campos contiver qualquer um que especifique o uso de validator nas regras de verificação para verificação auxiliar, todo o método validateFields não terá efeito.

No final, descobri que era porque eu nem sempre retornava callback() no retorno de chamada validator no início (acho que é muito mais do que isso, e você pode fazer para uma única entrada sem escrever no início. Verificação normal). Depois de adicionar, está tudo bem.

Confundir

Com licença, isso é um bug? Por não estar apontado no documento, validator deve ser retornado em callback() .
Se for necessário retornar callback , é recomendado lembrar o desenvolvedor no documento, ou pode ser padronizado por padrão.

segmento de código

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>

Ambiente

  • versão antd: mais recente
  • OS e sua versão: OS X
  • Navegador e sua versão: chrome mais recente
Usage ❓FAQ 🙅🏻‍♀️ WON'T RESOLVE

Comentários muito úteis

Recebi uma reclamação https://www.zhihu.com/question/33629737/answer/150154145

Você pode adicionar um documento afirmando que um dos nossos princípios de código aberto é cobrir a água e a terra.

Todos 38 comentários

É projetado: https://github.com/yiminghe/async-validator/

BTW, como o validador assíncrono sabe que um procedimento assíncrono terminou, se você não usa callback para notificá-lo?

Recebi uma reclamação https://www.zhihu.com/question/33629737/answer/150154145

Você pode adicionar um documento afirmando que um dos nossos princípios de código aberto é cobrir a água e a terra.

O documento foi atualizado.

Olá, esse uso só pode ser escrito em aula?
É possível escrever o React Component de uma forma puramente funcional. Em caso afirmativo, há algum caso?

Este design de API é realmente deselegante. Sinto que só quero verificar se uma determinada caixa de seleção está marcada:

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

E o primeiro parâmetro dado ao retorno de chamada é a mensagem de erro, que também é redundante com message (embora pareça que, enquanto algo for retornado, message será usado, ele deve ser coberto por message Mensagem de erro).

O uso esperado da maioria dos usuários deve ser retornar true ou false diretamente para determinar o que é certo ou errado:

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

Disponível, mas ainda é recomendável otimizar esta API, ou seja, usar https://github.com/yiminghe/async-validator/ , mas ANT pode ser preenchido aqui e pode ser encapsulado na chamada

@neekey pode enviar um PR compatível para o validador assíncrono

@neekey esta interface estranha deve alcançar:

  • Validação assíncrona
  • Suporta erros diferentes e retorna mensagens diferentes

Existe uma maneira melhor?

<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

Sempre que encontro a verificação de função, irei aqui para ver uma vez. É muito difícil lembrar

função de validador

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);
  }

Não é um erro de retorno de chamada unificado? Parece bastante razoável.
Não sei se a nova versão do antd começou a distinguir entre verificação assíncrona e síncrona? Validator (síncrono) asyncValidator (assíncrono)

Como chamar este prompt de mensagem no retorno de chamada retornado pelo plano de fundo após a solicitação

Eu encontrei um problema ao usar o validador na regra para fazer a verificação personalizada
validateFunc = (regra, valor, retorno de chamada) => {
se for verdade) {
console.log (11);
callback ('Mensagem de erro');
Retorna;
}
ligar de volta();
};
Desejo que o resultado da verificação 'Mensagem de erro' seja exibido no componente FormItem correspondente, mas depois que o retorno de chamada for executado, a 'Mensagem de erro' não será exibida no componente FormItem correspondente, mas será impressa no console. Por quê?

Como você escreve a lógica do seu 在对应的FormItem组件下显示 ?

@neekey pode ir e enviar um PR compatível para async-validator

Alguém mencionou isso, disse yiminghe, se opôs.

Como você escreve a lógica do seu 在对应的FormItem组件下显示 ?

Mudei o esquema de verificação customizado e julguei em onFieldsChange (), se as regras customizadas não forem atendidas, os erros serão alterados diretamente e as informações do erro serão exibidas no controle.
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, }, }); }

Por que o seguinte prompt não desaparece depois que a verificação é aprovada?

Faça uma pergunta, este validador não pode realizar a verificação quando a página é carregada?

@neekey
deve chamar um recurso de

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

e antes que setTimeout seja disparado, todo o componente é desmontado. Em seguida, o tempo limite é disparado, seu retorno de chamada é disparado e

componente usará setState (eu acho), o que resultará no seguinte erro:

Aviso: Não é possível realizar uma atualização de estado do React em um componente desmontado. Este é um ambiente autônomo, mas indica um vazamento de memória em seu aplicativo. Para corrigir, cancele todas as assinaturas e tarefas assíncronas no método componentWillUnmount.

Infelizmente, o retorno de chamada não pode ser cancelado! Não há como evitar esse erro!

@jiufengdadi
Eu encontrei esse problema.
Minha solução é passar undefined para callback . O validador passará quando o primeiro parâmetro de callback for um array vazio. E definiu um valor padrão para o parâmetro, então undefined também funciona.

a callback definição: L146

Por que async-validator: [""] aparece depois que minha validação personalizada é aprovada,

Se houver duas verificações, a primeira falhará. Por quê?
`` `
as regras: [
{
obrigatório: verdadeiro,
mensagem: 'Por favor, digite seu número de telefone',
},
{
validador: (regra, valor, retorno de chamada) => {
experimentar {
if (this.props.form.getFieldValue ('prefix') == 86 && value) {
const reg = / ^ 1d {10} $ /;
if (! reg.test (valor)) {
lançar um novo erro ('Algo errado!');
}
}
} catch (errar) {
retorno de chamada (errar);
}
},
mensagem: 'Digite um número de celular válido',
},
],

 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: '请输入有效手机号',
                },
              ],

Eu encontrei um problema ao usar o validador na regra para fazer a verificação personalizada
validateFunc = (regra, valor, retorno de chamada) => {
se for verdade) {
console.log (11);
callback ('Mensagem de erro');
Retorna;
}
ligar de volta();
};
Desejo que o resultado da verificação 'Mensagem de erro' seja exibido no componente FormItem correspondente, mas depois que o retorno de chamada for executado, a 'Mensagem de erro' não será exibida no componente FormItem correspondente, mas será impressa no console. Por quê?

Eu encontrei um problema ao usar o validador na regra para fazer a verificação personalizada
validateFunc = (regra, valor, retorno de chamada) => {
se for verdade) {
console.log (11);
callback ('Mensagem de erro');
Retorna;
}
ligar de volta();
};
Desejo que o resultado da verificação 'Mensagem de erro' seja exibido no componente FormItem correspondente, mas depois que o retorno de chamada for executado, a 'Mensagem de erro' não será exibida no componente FormItem correspondente, mas será impressa no console. Por quê?

Você resolveu, encontrou a mesma situação

 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: '请输入有效手机号',
                },
              ],

O prompt da mensagem será repetido? 'Por favor, insira um número de telefone celular, por favor, insira um número de telefone celular válido' semelhante a este

 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: '请输入有效手机号',
                },
              ],

O prompt da mensagem será repetido? 'Por favor, insira um número de telefone celular, por favor, insira um número de telefone celular válido' semelhante a este

Não vou

image

Faça o seguinte
image

Por que o cheque vermelho não desapareceu? ? ? Como fazer esse tipo de verificação de influência mútua que atenda às especificações? ? ?

O retorno de chamada do validador da regra deve ser chamado se for bem-sucedido ou falhar. A diferença é que os parâmetros não são passados.

Eu encontrei um problema ao usar o validador na regra para fazer a verificação personalizada
validateFunc = (regra, valor, retorno de chamada) => {
se for verdade) {
console.log (11);
callback ('Mensagem de erro');
Retorna;
}
ligar de volta();
};
Desejo que o resultado da verificação 'Mensagem de erro' seja exibido no componente FormItem correspondente, mas depois que o retorno de chamada for executado, a 'Mensagem de erro' não será exibida no componente FormItem correspondente, mas será impressa no console. Por quê?

Eu encontrei um problema ao usar o validador na regra para fazer a verificação personalizada
validateFunc = (regra, valor, retorno de chamada) => {
se for verdade) {
console.log (11);
callback ('Mensagem de erro');
Retorna;
}
ligar de volta();
};
Desejo que o resultado da verificação 'Mensagem de erro' seja exibido no componente FormItem correspondente, mas depois que o retorno de chamada for executado, a 'Mensagem de erro' não será exibida no componente FormItem correspondente, mas será impressa no console. Por quê?

Você resolveu, encontrou a mesma situação

Eu também encontrei este problema. Se o valor inicial estiver vazio, o validador personalizado pode ser disparado normalmente através do tempo onblur após a entrada normal e um prompt será fornecido se houver um erro, mas uma vez que o valor inicial inicial tem um valor, Quando validatefields executa a validação unificada de todos os componentes do formulário, err imprime como nulo e, após um tempo, a falha de validação aparecerá no console novamente. O validador personalizado é uma ação assíncrona

Acho que você exclui o retorno; na função e tenta novamente. Pode ser útil.

------------------ A mensagem original ------------------
De: "Ivan-hl" < [email protected]>;
Prazo de entrega: 20 de novembro de 2019 (quarta-feira) 17:19
Destinatário: "ant-design / ant-design" < [email protected]>;
Cc: "wk" < [email protected]>; "Manual" < [email protected]>;
Assunto: Re: [ant-design / ant-design] por que sempre precisamos de callback() na função de validador no componente Form? Por que o corpo do método sempre precisa chamar callback () ao usar o validador nas regras do formulário validação? (# 5155)

Eu encontrei um problema ao usar o validador na regra para fazer a verificação personalizada
validateFunc = (regra, valor, retorno de chamada) => {
se for verdade) {
console.log (11);
callback ('Mensagem de erro');
Retorna;
}
ligar de volta();
};
Desejo que o resultado da verificação 'Mensagem de erro' seja exibido no componente FormItem correspondente, mas depois que o retorno de chamada for executado, a 'Mensagem de erro' não será exibida no componente FormItem correspondente, mas será impressa no console. Por quê?

Eu encontrei um problema ao usar o validador na regra para fazer a verificação personalizada
validateFunc = (regra, valor, retorno de chamada) => {
se for verdade) {
console.log (11);
callback ('Mensagem de erro');
Retorna;
}
ligar de volta();
};
Desejo que o resultado da verificação 'Mensagem de erro' seja exibido no componente FormItem correspondente, mas depois que o retorno de chamada for executado, a 'Mensagem de erro' não será exibida no componente FormItem correspondente, mas será impressa no console. Por quê?

Você já resolveu, encontrou a mesma situação

Eu também encontrei este problema. Se o valor inicial estiver vazio, o validador personalizado pode ser disparado normalmente através do tempo onblur após a entrada normal e um prompt será fornecido se houver um erro, mas uma vez que o valor inicial inicial tem um valor, Quando validatefields executa a validação unificada de todos os componentes do formulário, err imprime como nulo e, após um tempo, a falha de validação aparecerá no console novamente. O validador personalizado é uma ação assíncrona

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub ou cancele a inscrição.

Que pena

Se houver uma exceção na função de verificação, não haverá prompt.
Pitted por muito tempo. . .

Eu me pergunto se este AntdV não é mantido

@ kongling94 ?

Encontrou o mesmo problema, sem mais texto?

<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>
Clique para confirmar que não há resposta e nenhum prompt, digite async-validator: ["o código é necessário"] no console
Não insira validateFields de todo
Remova validator e validateTrigger e clique em OK e ele aparecerá normalmente.
Qual é o problema?

<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>
Clique para confirmar que não há resposta e nenhum prompt, digite async-validator: ["o código é necessário"] no console
Não insira validateFields de todo
Remova validator e validateTrigger e clique em OK e ele aparecerá normalmente.
Qual é o problema?

Você resolveu este problema?Também encontrou este problema

<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>
Clique para confirmar que não há resposta e nenhum prompt, digite async-validator: ["o código é necessário"] no console
Não insira validateFields de todo
Remova validator e validateTrigger e clique em OK e ele aparecerá normalmente.
Qual é o problema?

Você resolveu este problema?Também encontrou este problema

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

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

validatorFun (regra, valor, retorno de chamada) {
const psw = this.form.getFieldValue ('newPwd')
if (valor && valor! == psw) {
rule.message = '两次 密码 不一致'
retorno de chamada (regra)
}
ligar de volta()
}

Esta página foi útil?
0 / 5 - 0 avaliações