Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react dynamic form values with antd

Dynamic forms with react and antd are eluding me. I have scoured the web looking for answers to no avail. Here is a codepen with a recreation of the issue I am having: https://codepen.io/sethen/pen/RwrrmVw

Essentially, the issue boils down to when you want loop through a bunch of values that are stored in state, like so:

class MyClass extends React.Component<{}, {}> {
  constructor(props) {
    super(props);

    this.state = {
      data: [
        { name: 'foo' },
        { name: 'bar' },
        { name: 'baz' }
      ]
    };
  }

You can think of these values as being fetched from some remote API.

As you can see, I have an array of objects with the key of name in the state. Further on down in the render cycle is the following:

return data.map((value, index) => {
      const { name } = value;

      return (
        <Form key={ index } initialValues={ { name } }>
          <Form.Item name='name'>
            <Input type='text' />
          </Form.Item>

          <Button onClick={ this.handleOnDeleteClick.bind(this, index) }>Delete</Button>
        </Form>
      );

This attempts to loop through the values stored in the state and put the values into an input. It also adds a little delete button to get rid of that item. The first time it renders, it does as you expect it to loading the value into the input value.

The issue is when you try to delete one of the items, like the middle one, it will delete the next item. The core of the issue is that the render is acting different than I expect it to when deleting an item. I am expecting that when I delete an item, it will take it out of state and load the ones that are left. This is not happening.

My question is, how am I able to load dynamic data in this way with antd whilst being able to delete each item?

like image 972
Sethen Avatar asked Jul 29 '26 04:07

Sethen


1 Answers

The main mistake in this form that you assign the key property as the array index, and on deleting the middle item, the last component will get a new key.

In React, changing the key will unmount the component and lose its state.

Don’t pass something like Math.random() to keys. It is important that keys have a “stable identity” across re-renders so that React can determine when items are added, removed, or re-ordered. Ideally, keys should correspond to unique and stable identifiers coming from your data, such as post.id.

Also, in your example, you actually render three forms instead of a single form and three fields.

Every <form/> has in its inner state all states of its form fields, so you will have a single object with all input values in it.

Antd.Form just a wrapper for such form, you can get Form.Item values in onFinish callback for example.

class MyClass extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      data: [{ name: "foo" }, { name: "bar" }, { name: "baz" }]
    };
  }

  handleOnDeleteClick = index => {
    this.setState({
      data: [
        ...this.state.data.slice(0, index),
        ...this.state.data.slice(index + 1)
      ]
    });
  };

  render() {
    const { data } = this.state;

    return (
      <Form>
        {data.map(({ name }, index) => {
          return (
            <Form.Item key={name}>
              <Input type="text" />
              <Button onClick={() => this.handleOnDeleteClick(index)}>
                Delete
              </Button>
            </Form.Item>
          );
        })}
      </Form>
    );
  }
}

Edit reverent-nash-dlqxb

like image 71
Dennis Vash Avatar answered Jul 30 '26 19:07

Dennis Vash



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!