React:如何在不出现“Warning: validateDOMNesting: <form> cannot appear as a descendant of <form>”警告的情况下使用子FormItem组件?

23

给定父组件,我正在使用一个子组件DynamicFieldSet,它是一组FormItems。 但是我收到以下错误:

警告:validateDOMNesting(...):<form>不能作为<form>的后代出现。请参见CreateTopic>Form>form>...>DynamicFieldSet>Form>form。

我已经尝试删除子组件中的<Form></Form>标签,但这将导致编译错误。

是否有一种方法可以禁用子表单视图的呈现?

父组件

class CreateTopic extends React.Component {
render() {
    return (
      <div className="create-topic-container">
        <h3>Create an event</h3>
        <Form onSubmit={this.handleSubmit}>
          <FormItem>...</FormItem>
          <FormItem>...</FormItem>
          <FormItem>...</FormItem>
          <FormItem
            {...formItemLayout}
            label="Results"
            style={{ marginBottom: SPACING_FORM_ITEM }}
          >
            {getFieldDecorator('results', {
              rules: [
                {
                  required: true,
                  message: 'Results cannot be empty.',
                },
              ],
            })(<DynamicFieldSet
              form={this.props.form}
            />)}
          </FormItem>
        </Form>
      </div>
    );
  }
}

DynamicFieldSet - 子组件

export class DynamicFieldSet extends React.Component {
  render() {
    getFieldDecorator('keys', { initialValue: ['0', '1'] });
    const keys = getFieldValue('keys');
    const formItems = keys.map((k, index) => {
      return (
        <FormItem
          {...formItemLayoutWithOutLabel}
          required={false}
          key={k}
        >
          {getFieldDecorator(`results[${k}]`, {
            validateTrigger: ['onChange', 'onBlur'],
            rules: [
              {
                required: true,
                whitespace: true,
                message: 'Result name cannot be empty.',
              },
              {
                validator: this.validateLength,
              },
            ],
          })(<Input placeholder={`Result #${index + 1}`} style={{ width: '80%', marginRight: 8 }} />)}
          {keys.length > 2 ? (
            <Icon
              className="dynamic-delete-button"
              type="minus-circle-o"
              disabled={keys.length === 1}
              onClick={() => this.remove(k)}
            />
          ) : null}
        </FormItem>
      );
    });

    return (
      <Form>
        {formItems}
        <FormItem {...formItemLayoutWithOutLabel}>
          {keys.length < 10 ? (
            <Button type="dashed" onClick={this.add} style={{ width: '80%' }}>
              <Icon type="plus" />Add Result
            </Button>
          ) : null}
        </FormItem>
      </Form>
    );
  }
}

1
你从哪个库中导入了表单组件? - Dyo
@Dyo 我正在使用 antd 来构建表单组件。 - The Nomad
4个回答

30
当我使用ant design table时遇到了这个问题,结果发现不是ant design引发的警告,而是Web标准中的描述"每个表单都必须嵌套在一个FORM元素中。在一个文档中可以有多个表单,但FORM元素不能嵌套。" 因此,一个表单标签内部不应该再包含另一个表单标签。
为了解决这个问题(在我们的情况下),请移除DynamicFieldSet“return”内部的Form标签,并用div标签替换。
希望对您有所帮助 :)

3
Ant Design有一个component属性,当在嵌套的表单上将其设置为false时,会删除嵌套的Form标签和错误,使其看起来就像没有嵌套一样正常工作。 - quazar
1
如果您将component设置为false,请再次测试代码的工作情况,因为它可能会导致意外行为。 - StarLord
@StarLord,可能会有哪些意外行为? - nerdess

8
您可以像这样进行表单传送:
import Portal from '@material-ui/core/Portal';

const FooComponent = (props) => {
   const portalRef = useRef(null);

   return <>
      <form>
        First form
        <div ref={portalRef} />
      </form>
      <Portal container={portalRef.current}>
        <form>Another form here</form>
      </Portal>
   </>;
}

在上面的示例中,我使用了 React Material-UI Portal 组件。但是你也可以尝试使用 React Portals 实现它。

谢谢!这个答案启发了我使用React Portal,而且它很有效。 - Brody Chen
虽然它能工作,但不是嵌套形式。 - Hidayt Rahman
感谢指出React Portals。Headless UI(我正在使用的框架)也有门户。这对我解决了问题。 - Sushant Rajbanshi

4
如果你正在使用 MUI,Box 组件包含一个属性,用于将其标识为任何原生 HTML 容器之一;其中之一便是表单。例如:
<Box
   xs={6}
   sx={{
       "& > :not(style)": { m: 1, width: "25ch" },
       }}
   component="form"
   noValidate
   autoComplete="off"
>

在这种情况下,我们只需要删除该属性,它将默认为 DIV。表单将按预期工作,并且错误消息将从控制台中消失。

2
在我的情况下,这是发生的原因是我在另一个 <form/> 标签内声明了 <form>

3
这是我需要的,谢谢! - Hoàng Vũ Tgtt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接