Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: how to use child FormItem components without getting Warning: validateDOMNesting: <form> cannot appear as a descendant of <form>

Given the parent component, I am using a child component DynamicFieldSet that is a grouping of FormItems. But I am receiving the error:

Warning: validateDOMNesting(...): <form> cannot appear as a descendant of <form>. See CreateTopic > Form > form > ... > DynamicFieldSet > Form > form.

I have tried to remove the <Form> </Form> tags in my child component, but then it is a compile error.

Is there a way I can disable rendering of the child Form view?

Parent component

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 - Child component

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>
    );
  }
}
like image 660
The Nomad Avatar asked Feb 05 '18 09:02

The Nomad


2 Answers

I faced this issue when using ant design table and turns out its not ant design which throws the warning. It's the web standards description

"Every form must be enclosed within a FORM element. There can be several forms in a single document, but the FORM element can't be nested."

So, there should not be a form tag inside a form tag.

To solve the issue (in our case), remove the Form tag inside the DynamicFieldSet "return" and replace with a div tag

Hope it helps :)

like image 191
Thinker Avatar answered Sep 18 '22 15:09

Thinker


You can portal a form like this:

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

In the example above I use the react material-ui Portal component. But you can try to implement it with React Portals as well

like image 23
BigBadAlien Avatar answered Sep 18 '22 15:09

BigBadAlien