简体   繁体   中英

Antd Modal how to update the value in it

I'm using Antd Modal to display order information by passing props to TableDetail Component. The thing is when I try to remove the items in the order I use setState and the modal won't update its data.

https://codesandbox.io/s/antd-reproduction-template-forked-vu3ez A simple version of reproduction is provided above.

enter image description here After I click on the remove button the items remain unchanged but when I close and open the modal it will update. enter image description here

What should I do to make it change? I tried forceUpdate() but it won't work.

Here is the TableDetail component.

export default class TableDetail extends Component {
  constructor(props) {
    super(props);
    this.state = {
      tableOrder: props.tableOrder,
      column: []
    };
  }

  tableInitializer = () => {
    const column = [
      {
        title: "name",
        render: (item) => {
          return <span>{item.name}</span>;
        }
      },
      {
        title: "price",
        render: (item) => {
          return item.price;
        }
      },
      {
        title: "amount",
        render: (item) => {
          return <span>{item.amount}</span>;
        }
      },
      {
        title: "removeButton",
        render: (item) => {
          return (
            <Button
              type="link"
              style={{ color: "red" }}
              onClick={() => this.props.removeItem(item)}
            >
              Remove
            </Button>
          );
        }
      }
    ];
    this.setState({
      column
    });
  };

  UNSAFE_componentWillMount() {
    this.tableInitializer();
  }

  render() {
    return (
      <Modal
        visible={true}
        title={
          <span style={{ fontSize: "1.5rem", fontWeight: "bold" }}>
            Table: {this.state.tableName}
          </span>
        }
        cancelText="Cancel"
        okText="OK"
        onCancel={this.props.hideModal}
      >
        <Table
          columns={this.state.column}
          dataSource={this.state.tableOrder}
          rowKey="name"
        />
      </Modal>
    );
  }
}

TableDetail.propTypes = {
  tableOrder: PropTypes.array.isRequired,
  tableName: PropTypes.string.isRequired,
  hideModal: PropTypes.func.isRequired,
  removeItem: PropTypes.func.isRequired
};

The issue in your code is in removeItem . You are trying to mutate tableOrder. According to react docs :

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

So that is why it is kind of asynchronous and you can't see your updated changes. You need to do this:

removeItem = (item) => {
    const { tableOrder } = this.state;
    const newTable = [...tableOrder]; <- Create new variable and update variable
    for (let i = 0; i < newTable.length; i++) {
      if (item.name === newTable[i].name) {
        console.log("Got it! " + newTable[i].name);
        newTable.splice(i, 1);
        console.log("new table: ", tableOrder);
        break;
      }
    }
    this.setState({
      tableOrder: newTable <- update here
    });
  };

You dont need to actually modify array you can simply do this also:

this.setState(
{
tableOrder: this.state.tableOrder.filter(data => !(data.name===item.name))
}
)
//filter creates new array

Here is demo: https://codesandbox.io/s/antd-reproduction-template-forked-j4bfl?file=/tables.js

You can use the filter method in your removeItem function

  removeItem = (item) => {
    const filtered = this.state.tableOrder.filter(
      (order) => item.name !== order.name
    );
    console.log(item, filtered);
    this.setState({
      tableOrder: filtered
    });
  };

and one more thing you should avoid assigning your props to state like

   this.state = {
      tableOrder: props.tableOrder,
    };

instead of assigning to state directly use that as props like

     <Table
      dataSource={this.props.tableOrder}
     />

In most cases, this is an antipattern. Don't “copy props into state.” It creates a second source of truth for your data, which usually leads to bugs. One source of truth is best.

Improved code Live demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM