Ant-design: A instância criada por `useForm` não está conectada a nenhum elemento Form. Esqueça-se de passar a propriedade` form`? Obviamente segue o exemplo.

Criado em 23 fev. 2020  ·  56Comentários  ·  Fonte: ant-design/ant-design

  • [] Eu pesquisei os problemas deste repositório e acredito que este não é uma duplicata.

Link de reprodução

https://next.ant.design/components/form-cn/#components -form-demo-form-in-modal

Passos para reproduzir

Basta usar useForm diretamente. Refiro-me ao exemplo na camada pop-up.

const CollectionCreateForm = ({onCancel}) => {
const [form] = Form.useForm ();
form.setFieldsValue ({
categoryName: caseDetail.categoryName,
});
Retorna (
visível = {visível}
maskClosable = {false}
title = "Modificar as informações básicas do projeto"
okText = "OK"
cancelText = "Cancelar"
onCancel = {onCancel}
onOk = {() => {
Formato
.validateFields ()
.então (valores => {
form.resetFields ();
onCreate (valores);
})
.catch (info => {
window.console.log ('Falha na validação:', informações);
});
}}
>

form = {form}
layout = "vertical"
nome = "form_in_modal"
initialValues ​​= {{
modificador: 'public',
}}
>



nome = "título"
rótulo = "Título"
regras = {[
{
obrigatório: verdadeiro,
mensagem: 'Por favor, insira o título da coleção!',
},
]}
>







);
};

O que é esperado?

Eu só quero poder usar este useForm normalmente

O que realmente está acontecendo?

index.js: 1 Aviso: a instância criada por useForm não está conectada a nenhum elemento do formulário. Esqueceu de passar form prop?
em CollectionCreateForm ....

const [formulário] = Form.useForm ();
form.setFieldsValue ({
categoryName: caseDetail.categoryName,
});

form = {form}
layout = "vertical"
nome = "form_in_modal"
initialValues ​​= {{
modificador: 'public',
}}
>

| Meio ambiente | Informações |
| --- | --- |
| antd | 4.0.0-rc.5 |
| Reagir | 16.8.6 |
| Sistema | mac10.15.3 |
| Navegador | cromo |


Vim diretamente de acordo com o site oficial, mas esse erro foi relatado em todos os lugares, e eu fiquei sem palavras.

❓FAQ

Comentários muito úteis

Resolvi. No drawer, usar getContainer = {false} pode resolver. Acho que o Modal é o mesmo.
Eu uso getContainer = {false} na gaveta. O Modal também deve ter o mesmo problema. Você pode tentar

Todos 56 comentários

image

Olá @LamTech. Forneça uma reprodução online bifurcando este link https://u.ant.design/codesandbox-repro ou um repositório GitHub mínimo. Problemas marcados por Need Reproduce serão fechados se não houver atividades em 7 dias .

Olá @LamTech , precisamos que você forneça um exemplo aqui para criar um codesandbox ou fornecer um repositório GitHub mínimo. Os problemas que não forem acompanhados em 7 dias serão encerrados automaticamente.

A chave é que eu uso esse método, mas ele continua relatando esse aviso de erro.

O mesmo problema aqui, mas não podemos reproduzi-lo no codesandbox.

+1

Adicione o atributo forceRender ao Modal

Você pode adicionar um atraso ao método setFieldsValue

Chame form.resetFields (); é o que parece. O http: // localhost : 8001 / components / form-cn / # components-form-demo-form-context iniciado localmente será relatado.

+1
Este aviso aparecerá ao usar setFieldsValue, mas pode ser apresentado sem problemas,
Passei na instância de useForm

O formulário no Modal não será renderizado por padrão, você pode consultar a resposta de @ se7en00 e adicionar forceRender ao Modal. Ou chame setFieldsValue e resetFields depois que Modal for exibido e a renderização for concluída.

Ao usar a versão V4 (existe formulário no componente de função), fiquei incomodado com esse problema por dois dias e quase caí (foi relatado um erro, mas não afetou o uso). Por fim, li https://ant.design / e https: // next. .ant.design / Descubra o uso de formulário em componentes de função e classes deve compreender e distinguir entre os componentes de função
useEffect (() => {
return () => {
form.resetFields ();
};
})
É todo o componente da função que aciona a destruição em return () => {....} (não testado se o formulário foi destruído neste momento)
Descrição do documento: destroyOnClose | Destrua os elementos filhos do Modal ao fechar, o padrão é falso. forceRender | Renderização obrigatória de Modal, padrão falso.
Solução: Modal's forceRender = true, destroyOnClose = false, quando Modal for destruído (fechado), nenhum erro será reportado. O formulário pode ser encontrado quando o código interno é executado, mas o aviso de id de controle de entrada repetido será relatado (é mais elegante que o erro).

Mesmo problema +1

se o seu código envolve setFieldsValue ou outras funções semelhantes, chame-o após os nós renderizados

useEffect(() => {
  form.setFieldsValue({
    id: 1
  })
}, [])

ou

componentDidMount() {
  form.setFieldsValue({
    id: 1
  })
}

Resolveu meu problema

Acho que nenhuma das opções acima pode resolver completamente este problema. Você pode adicionar um atributo ao formulário para indicar se o formulário tem campos e deixar que o próprio desenvolvedor determine se deve executar o código a seguir

O mesmo acontece aqui

Ainda não corrigido?

Tentei todos os métodos mencionados acima, não funcionou

O formulário no Modal não será renderizado por padrão, você pode consultar a resposta de @ se7en00 e adicionar forceRender ao Modal. Ou chame setFieldsValue e resetFields depois que Modal for exibido e a renderização for concluída.

Quando eu uso a gaveta, embora o Drawer tenha a API forcerender, a API da gaveta, que é diferente do Modal, não é a renderização forçada, mas a pré-renderização, e então o mesmo erro é relatado, então existe uma solução? Como julgar que a renderização está completa?

Resolvi. No drawer, usar getContainer = {false} pode resolver. Acho que o Modal é o mesmo.
Eu uso getContainer = {false} na gaveta. O Modal também deve ter o mesmo problema. Você pode tentar

Você pode usar useRef para salvar o objeto Form e pode determinar se useRef existe antes de usar o formulário;

mesmo problema aqui. formulário é atribuído, mas continua falhando.

Se você chamar form.setFieldsValue diretamente no efeito, mesmo se forceRenter for adicionado e o Modal reaberto, ainda haverá este aviso. A solução temporária só pode ser setTimeout (() => form.setFieldsValue, 0) no efeito.

Para resolver o problema da gaveta, usei getContainer = {false} e não reportei o aviso.Se o mesmo problema ocorrer, você pode tentar e esperar que possa ser escrito claramente no documento Form.

Obrigado, este método resolveu o mesmo problema 👍

Seu método é viável, você pode explicar o princípio?

Minha solução alternativa, crie um ref por useState quando Form foi renderizado, então verifique ref antes de usar a instância do formulário.

interface FormModalProps {
  data?: RoleProps;
  visible: boolean;
  onCancel?: () => void;
  onSubmit?: (values: Store) => void;
  submitting: boolean;
}

const FormModal: React.FC<FormModalProps> = props => {
  const [form] = Form.useForm();
  const [formRef, setFormRef] = useState();  // <---- set the ref when Form Rendered

  const { data, onSubmit, onCancel, visible, submitting } = props;

  // reset Form when modal close
  useEffect(() => {
    if ( !props.visible && formRef) {  // <---- check ref before use the form instance
      form.resetFields();
    }
  }, [props.visible]);

  // fill Form when modal open
  useEffect(() => {
    if (visible && formRef) {   // <---- check ref before use the form instance
      form.setFieldsValue({
        ...data,
      });
    }
  }, [props.data]);

  // handle form onFinish
  const handleFormFinish = (values: Store) => {
    if (onSubmit) {
      onSubmit(values);
    }
  };

  // handle modal  ok
  const handleOk = () => {
    if (!form) return;
    form.submit();
  };

  return (
    <Modal
      title="Modal"
      confirmLoading={submitting}
      onOk={handleOk}
      onCancel={onCancel}
      visible={visible}
      width={640}
    >
      <Form ref={setFormRef} form={form} onFinish={handleFormFinish}>
        <Form.Item name="title" label="Title" >
          <Input />
        </Form.Item>
      </Form>
    </Modal>
  );
};

Sem mais avisos de novo!

é difícil discutir em inglês?

se você usar setFieldsValue, tente seguir o código para substituir (minha ideia tola)。

<Modal        **destroyOnClose**      >
        <Form **initialValues={formValues}**>
        </Form>
</Modal>

Eu tenho que trabalhar.
Inicialmente, eu estava chamando o componente antd de
<Form blabla >

Em seguida, adicionei o prop de formulário no componente Form -

<Form form={form} blabla >

Aqui, o {form} vem de const [form] = Form.useForm();

Doc (que eu estava seguindo) -
https://ant.design/components/form/#components -form-demo-form-in-modal

Seu caso pode ser diferente.

https://codesandbox.io/s/form-in-modal-to-create-ant-design-demo-xvcyv
Mesmo problema, qualquer corpo pode consertar isso ??

Consulte linxianxi acima, https://github.com/ant-design/ant-design/issues/21543#issuecomment -598515368

Modal eu posso

 <Modal
  destroyOnClose={false} 
  getContainer={false}
  forceRender
>

Modal eu posso

 <Modal
  destroyOnClose={false} 
  getContainer={false}
  forceRender
>

Obrigado, resolvi este problema adicionando adereços forceRender no Modal

    const [form] = Form.useForm()

    <Form form={form} >
     ....

    </Form>```


         this did the trick for me.

Eu tenho que trabalhar.
Inicialmente, eu estava chamando o componente antd de
<Form blabla >

Em seguida, adicionei o prop de formulário no componente Form -

<Form form={form} blabla >

Aqui, o {form} vem de const [form] = Form.useForm();

Doc (que eu estava seguindo) -
https://ant.design/components/form/#components -form-demo-form-in-modal

Seu caso pode ser diferente.

Isso consertou para mim também. Eu estava usando o formulário em uma gaveta, não em um modal

A combinação secreta para mim foi:

useEffect (() => {
if (forma && visível) {
if (atual) {
setTimeout (() => form.setFieldsValue ({
...atual,
}), 0);
} outro {
form.resetFields ();
}
}
}, [atual]);

Mesmo erro aqui sem passagem modal e de prop de formulário para o componente de formulário
https://codesandbox.io/s/basic-usage-ant-design-demo-6llbw?file=/index.js : 1618-1661

Mesmo erro aqui sem passagem modal e de prop de formulário para o componente de formulário
https://codesandbox.io/s/basic-usage-ant-design-demo-6llbw?file=/index.js : 1618-1661

Correção para o seu: https://codesandbox.io/s/basic-usage-ant-design-demo-ksuz8?file=/index.js

você deve mover o form.getVieldValue para um componente Form.Item

        <Form.Item
          shouldUpdate={(prevValues, curValues) =>
            prevValues.username !== curValues.username
          }
          noStyle
        >
          {() => <div>{form.getFieldValue("username")}</div>}
        </Form.Item>

outro método seria usar um useRef ()

Draw + Form. Para Modal + Form, o método se aplica.

  1. forceRender = true, destroyOnClose = false. Funciona em um dos meus componentes, mas não funciona no outro. Acho que, devido à ligação entre Form.Item, meu código é
const MyComp = React.memo(() => {
     const [form] = Form.useForm();
     const { getFieldValue } = form;
     const category = getFieldValue('category'); // It's the culprit
     return (/* something */);
})

Uso adequado: métodos de formulário

<Form.Item
        noStyle
        shouldUpdate={(prevValues, currentValues) => prevValues.gender !== currentValues.gender}
      >
        {({ getFieldValue }) => {
          return getFieldValue('gender') === 'other' ? (
            <Form.Item name="customizeGender" label="Customize Gender" rules={[{ required: true }]}>
              <Input />
            </Form.Item>
          ) : null;
        }}
 </Form.Item>

  1. forceRender = true, destroyOnClose = false. Funciona em um dos meus componentes, mas não funciona no outro.Descobri que, devido à ligação entre os componentes, meu código é o seguinte
const MyComp = React.memo(() => {
     const [form] = Form.useForm();
     const { getFieldValue } = form;
     const category = getFieldValue('category'); // It's the culprit
     return (/* something */);
})

A maneira correta de usar: chamada de método de formulário

<Form.Item
        noStyle
        shouldUpdate={(prevValues, currentValues) => prevValues.gender !== currentValues.gender}
      >
        {({ getFieldValue }) => {
          return getFieldValue('gender') === 'other' ? (
            <Form.Item name="customizeGender" label="Customize Gender" rules={[{ required: true }]}>
              <Input />
            </Form.Item>
          ) : null;
        }}
 </Form.Item>

Isso acontece porque o elemento do formulário não foi renderizado, mas Você definiu valores para o formulário. Eu acho que este é um conhecimento básico sobre react e hooks .. Você pode usar setTimeout para esperar o formulário renderizado.

Mas a melhor maneira de definir o valor inicial do formulário é

<Form
   initialValues={{ 
      name: 'Hafid',
      age: '35'
}}
onFinish={onFinish}
>

ou com este método

`` `js
const [valores, setValues] = React.useState ({})

React.useEffect (() => {
// obter valores de dados de serviço da web ou API
// fecth (...)
if (values_from_api) {
setValues ​​(values_from_api);
}
}, [])

return <>

initialValues ​​= {valores}
onFinish = {onFinish}
>

E se eu precisar usar valores de formulário em meu próprio gancho personalizado?
Com o Ant 3 eu fiz assim:

const [updating, updateInfo] = useMyOwnCustomHookForSubmitAction(getFieldsValue());

const submitForm = () => {
   validateFields((err) => {
        if (!err) updateInfo();
   });
};

<Form>...</Form>

Com o Ant 4, se eu tentar fazer assim, vou obter este erro do tópico.

const [form] = useForm();
const [updating, updateInfo] = useMyOwnCustomHookForSubmitAction(getFieldsValue());

const submitForm = () => {
   validateFields((err) => {
        if (!err) updateInfo();
   });
};

<Form form={form}>...</Form>

O formulário está em modal, forceRender = true, destroyOnClose = false definido. O que estou fazendo de errado?

Ao usar a versão V4 (existe um formulário no componente de função), fiquei incomodado com esse problema por dois dias e quase caí (foi relatado um erro, mas não afetou o uso) .Finalmente, li https: // ant. design / e https: // next. .ant.design / Descubra o uso de forma em componentes de função e classes deve compreender e distinguir entre os componentes de função
useEffect (() => {
return () => {
form.resetFields ();
};
})
É todo o componente da função que aciona a destruição em return () => {....} (não testado se o formulário foi destruído neste momento)
Descrição do documento: destroyOnClose | Destrua os elementos filhos do Modal ao fechar, o padrão é falso. forceRender | Renderização obrigatória de Modal, padrão falso.
Solução: Modal's forceRender = true, destroyOnClose = false, quando Modal for destruído (fechado), nenhum erro será reportado. O formulário pode ser encontrado quando o código interno é executado, mas o aviso de id de controle de entrada repetido será relatado (é mais elegante que o erro).

Eu também encontrei esse problema, resolvi dessa forma
Configuração modal forceRender | Renderização forçada
No formulário Modla, name = {['modal', 'cityCode']}
Name = {['search', 'cityCode']} ou name = 'cityCode' no formulário de filtro
Desta forma, todos os avisos podem ser resolvidos e os 2 elementos encontrados com aviso de ID não exclusivo não serão relatados ⚠

Você pode usar useRef para se referir à ref do formulário, use o método em formRef.current

const formRef = useRef()

return (<Form ref={formRef}>
  {
    (formRef.current && formRef.current.getFieldsValue('key') === 1) 
     &&
   (<Input />)
  }
</Form>)

O formulário no Modal não será renderizado por padrão, você pode consultar a resposta de @ se7en00 e adicionar forceRender ao Modal. Ou chame setFieldsValue e resetFields depois que Modal for exibido e a renderização for concluída.

Adicionar o atributo forceRender ao Modal é totalmente inútil

O exemplo no bloco oficial também avisa

Ao usar a versão V4 (existe um formulário no componente de função), fiquei incomodado com esse problema por dois dias e quase caí (foi relatado um erro, mas não afetou o uso) .Finalmente, li https: // ant. design / e https: // next. .ant.design / Descubra o uso de forma em componentes de função e classes deve compreender e distinguir entre os componentes de função
useEffect (() => {
return () => {
form.resetFields ();
};
})
É todo o componente da função que aciona a destruição em return () => {....} (não testado se o formulário foi destruído neste momento)
Descrição do documento: destroyOnClose | Destrua os elementos filhos do Modal ao fechar, o padrão é falso. forceRender | Renderização obrigatória de Modal, padrão falso.
Solução: Modal's forceRender = true, destroyOnClose = false, quando Modal for destruído (fechado), nenhum erro será reportado. O formulário pode ser encontrado quando o código interno é executado, mas o aviso de id de controle de entrada repetido será relatado (é mais elegante que o erro).

Este método pode ser resolvido, mas se o operador ternário estiver visível? É usado para determinar a camada externa de Modal e forceRender = true, destroyOnClose = false é assim:
{visible ? : <Modal visible={visible} forceRender destroyOnClose={false}><Form form={form} onFinish={handleFinish}>...</Form></Modal> : null}
Há um problema: apenas a máscara é exibida, mas a caixa com marcadores não é exibida

Defina forceRender = true e destroyOnClose = false desta forma e, em seguida, use form.resetFields () quando o pop-up for fechado onOk ou onCancel e nenhum outro erro será relatado.
<Modal visible={visible} forceRender destroyOnClose={false} > <Form form={form} onFinish={handleFinish}>...</Form> </Modal>
Mas se você usar o operador ternário visible? Para determinar a camada externa do Modal e definir forceRender = true, destroyOnClose = false assim:
{visible ? <Modal visible={visible} forceRender destroyOnClose={false} > <Form form={form} onFinish={handleFinish}>...</Form> </Modal> : null }
Há um problema: apenas a máscara é exibida, mas a caixa com marcadores não é exibida

A solução oficial
image
Ligação

Ao usar a versão V4 (existe um formulário no componente de função), fiquei incomodado com esse problema por dois dias e quase caí (foi relatado um erro, mas não afetou o uso) .Finalmente, li https: // ant. design / e https: // next. .ant.design / Descubra o uso de forma em componentes de função e classes deve compreender e distinguir entre os componentes de função
useEffect (() => {
return () => {
form.resetFields ();
};
})
É todo o componente da função que aciona a destruição em return () => {....} (não testado se o formulário foi destruído neste momento)
Descrição do documento: destroyOnClose | Destrua os elementos filhos do Modal ao fechar, o padrão é falso. forceRender | Renderização obrigatória de Modal, padrão falso.
Solução: Modal's forceRender = true, destroyOnClose = false, quando Modal for destruído (fechado), nenhum erro será reportado. O formulário pode ser encontrado quando o código interno é executado, mas o aviso de id de controle de entrada repetido será relatado (é mais elegante que o erro).

Eu também encontrei esse problema, resolvi dessa forma
Configuração modal forceRender | Renderização forçada
No formulário Modla, name = {['modal', 'cityCode']}
Name = {['search', 'cityCode']} ou name = 'cityCode' no formulário de filtro
Desta forma, todos os avisos podem ser resolvidos e os 2 elementos encontrados com aviso de ID não exclusivo não serão relatados ⚠

[O nome do formulário será usado como o prefixo do id do campo do formulário] Portanto, não há aviso sobre 2 elementos encontrados com id não exclusivo

getContainer = {false} como propriedade modal + ter o modal visível quando chamo form.resetFields () funciona para eu não mostrar o aviso

useEffect(() => {
    if (form && visible) {
      form.resetFields();
    }
  }, [visible]);

Desta forma, destroyOnClose também pode ser verdadeiro

Eu uso useRef em vez de Form.useFrom para obter a instância do Form, funciona para mim

  const [visible, setVisible] = useState(false)

  let form = useRef(null)

  const closeModal = () => {
    setVisible(false)
    form.resetFields()
  }

  return (
    <Modal
      title="test"
      visible={visible}
      onCancel={closeModal}
      footer={null}
    >
      <Form
        name="test"
        layout="vertical"
        onFinish={onFinish}
        ref={instance => { form = instance }}
      >
        <Form.Item
          label="item"
          name="item"
        >
          <Input />
        </Form.Item>
        <Form.Item
          style={{
            textAlign: 'right',
          }}
        >
          <Space size="middle">
            <Button type="primary" htmlType="submit">
             submit
            </Button>
            <Button onClick={closeModal}>
             cancle
            </Button>
          </Space>
        </Form.Item>
      </Form>
    </Modal>
)

Apenas meus dois centavos: esse erro apareceu para mim quando tentei redefinir um formulário que não estava montado, então adicionar uma dependência a uma constante necessária resolveu.

useEffect(() => {
  if (data) { // data is used to populate initialValues
    form.resetFields();
  }
}, [form, data])

EDITAR: praticamente o que @fabripeco disse: D

Eu uso o formulário no Popover, useRef pode ser usado para mim, acho que pode ser usado para modal

const formRef = useRef(null);

<Popover
  content={renderEdit()}
  visible={isEdit}
  onVisibleChange={onToggleEdit}
>
  <span onClick={onToggleEdit}>
    {name}
  </span>
</Popover>

function renderEdit() {
  return (
    <Form
      initialValues={{ newName: name }}
      form={form}
      ref={formRef}
    >
    </Form>
  );
}

function onToggleEdit() {
  if (isEdit) {
    toggleEdit(false);
  } else if (!isEdit) {
    if (formRef.current) {
      form.setFieldsValue({
        newName: name
      });
    }
    toggleEdit(true);
  }
}

Minha solução alternativa, crie um ref por useState quando Form foi renderizado, então verifique ref antes de usar a instância do formulário.

interface FormModalProps {
  data?: RoleProps;
  visible: boolean;
  onCancel?: () => void;
  onSubmit?: (values: Store) => void;
  submitting: boolean;
}

const FormModal: React.FC<FormModalProps> = props => {
  const [form] = Form.useForm();
  const [formRef, setFormRef] = useState();  // <---- set the ref when Form Rendered

  const { data, onSubmit, onCancel, visible, submitting } = props;

  // reset Form when modal close
  useEffect(() => {
    if ( !props.visible && formRef) {  // <---- check ref before use the form instance
      form.resetFields();
    }
  }, [props.visible]);

  // fill Form when modal open
  useEffect(() => {
    if (visible && formRef) {   // <---- check ref before use the form instance
      form.setFieldsValue({
        ...data,
      });
    }
  }, [props.data]);

  // handle form onFinish
  const handleFormFinish = (values: Store) => {
    if (onSubmit) {
      onSubmit(values);
    }
  };

  // handle modal  ok
  const handleOk = () => {
    if (!form) return;
    form.submit();
  };

  return (
    <Modal
      title="Modal"
      confirmLoading={submitting}
      onOk={handleOk}
      onCancel={onCancel}
      visible={visible}
      width={640}
    >
      <Form ref={setFormRef} form={form} onFinish={handleFormFinish}>
        <Form.Item name="title" label="Title" >
          <Input />
        </Form.Item>
      </Form>
    </Modal>
  );
};

Sem mais avisos de novo!

resolvido perfeitamente!

Duas razões para este Aviso:
1+
2. "form.setFields ()" ou outra função em useEffect ()

Eu resolvo usar isso:

<Modal
        getContainer={false}
        // destroyOnClose
>

A solução oficial
image
Ligação

Perfeito, adicione forceRender ao modal

Por que você não expõe formHooked e permite que os usuários julguem por si mesmos, você não se sente cansado com os métodos acima?

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