【问题标题】:ant design table 中的意外 useState 行为
【发布时间】:2022-01-23 16:16:08
【问题描述】:

我有ant design表单和table并排,当我填写表单数据并点击add entity button时,数据应该会显示在table中。现在,当我单击添加实体时,数据确实得到了呈现,但是当我再次填写表单并单击添加实体按钮时,以前的数据消失了,现在我知道我需要复制以前的数据,我也这样做了,但是它不工作。

我的问题:- 添加新表单数据时,表格中呈现的先前表单状态值会消失

我的查询:- 我应该如何以及在何处使用扩展运算符复制前一个对象,以便它不会被重置。

我的代码是

import { Card, Table } from "antd";
import { Form, Input, Button, Select, Space, AutoComplete } from "antd";
import { DeleteOutlined, PlusOutlined, SendOutlined } from "@ant-design/icons";
import { useState } from "react";


const ExampleComponent = (props) => {
  // Destructuring props
  const { intent_data, entity_data } = props;
  
  const [dataSource, setDataSource] = useState([{}]);
  // To handle the disable state of Select Entity Select DropDown
  const [addentity,setAddEntity] = useState(false)
  // Handler function passed to YES/NO Select Option
  const addEntityHandler = (addEntity) => {
    if(addEntity === 'no'){
      setAddEntity(true)
    }else{
      setAddEntity(false)
    }
  }
  
  const [form] = Form.useForm();
  const onFinish = (values) => {
    console.log(values);
    form.resetFields();
    const dataArr = [];
    // Push values to array since dataSource takes array not an object
    dataArr.push(values);
    setDataSource(dataArr);
  };
  const columns = [
    {
      title: "Entity",
      dataIndex: "entity_name",
      key: "entity_name",
    },
    {
      title: "Entity Value",
      dataIndex: "entity_value",
      key: "entity_value",
    },
    {
      title: "Operation",
      key: "operation",
      render: (record: any) => (
        <DeleteOutlined
          style={{ color: "red" }}
          onClick={() => console.log(record)}
        />
      ),
    },
  ];
  return (
    <Card className="csi-project-card-0934">
      <div className="example-layout">
        <div style={{ flexBasis: "100%" }}>
          <Form
            form={form}
            labelCol={{ span: 7 }}
            wrapperCol={{ span: 10 }}
            layout="horizontal"
            colon={true}
            onFinish={onFinish}
            size="large"
          >
            {/* <h4>Create Example</h4> */}
            <Form.Item
              label="Select Intent"
              name="intent_name"
              className="csi-ant-form-item"
              rules={[{ required: true, message: "Intent Cannot be Empty!" }]}
            >
              <Select>
                {/* {intent_data?.map?.((value) => (
                  <Select.Option
                    key={value.intent_ID}
                    value={value.intent_name}
                  >
                    {value.intent_name}
                  </Select.Option>
                ))} */}
                <Select.Option value="intent demo">Intent Demo</Select.Option>
                <Select.Option value="intent test">Intent Test</Select.Option>
              </Select>
            </Form.Item>
            <Form.Item
              label="Enter Example"
              name="example_name"
              className="csi-ant-form-item"
              hasFeedback
              rules={[
                { required: true, message: "This Field Cannot be Empty!" },
                ({ getFieldValue }) => ({
                  validator(_, value) {
                    if (value.length < 4) {
                      return Promise.reject("Length too short");
                    }
                    return Promise.resolve();
                  },
                }),
              ]}
            >
              <AutoComplete>
                <Input allowClear/>
              </AutoComplete>
            </Form.Item>
            <Form.Item
              label="Do you want to add Entity"
              name="add_entity"
              className="csi-ant-form-item"
              rules={[{ required: true, message: "This Cannot be Empty!" }]}
            >
              <Select placeholder="SELECT" onSelect={(addEntity) => addEntityHandler(addEntity)}>
                <Select.Option value="yes">YES</Select.Option>
                <Select.Option value="no">NO</Select.Option>
              </Select>
            </Form.Item>

            <Form.Item
              label="Select Entity"
              name="entity_name"
              className="csi-ant-form-item"
            >
              <Select disabled = {addentity}>
                <Select.Option value="entity demo">Entity Demo</Select.Option>
                <Select.Option value="entity test">Entity Test</Select.Option>
              </Select>
            </Form.Item>
            <Form.Item
              label="Select Value"
              name="entity_value"
              className="csi-ant-form-item"
              hasFeedback
              rules={[
                { required: true, message: "This Field Cannot be Empty!" },
              ]}
            >
              <AutoComplete>
                <Input placeholder="Select Value from Example" />
              </AutoComplete>
            </Form.Item>

            <Form.Item className="csi-ant-form-item">
              <Button
                key="submit"
                type="primary"
                htmlType="submit"
                shape="round"
              >
                Add Entity <PlusOutlined />
              </Button>
            </Form.Item>
          </Form>
        </div>
        <div
          style={{
            flexBasis: "100%",
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
          }}
        >
          <Table
            bordered
            className="ib-table"
            dataSource={dataSource}
            columns={columns}
            pagination={{ pageSize: 6 }}
            rowKey={Math.random().toString()}
          />
          <Button key="submit" type="primary" htmlType="submit" shape="round">
            Submit <SendOutlined />
          </Button>
        </div>
      </div>
    </Card>
  );
};
export default ExampleComponent;

表单数据存储在values对象中,values的结构是

{
add_entity: "yes"
entity_name: "entity demo"
entity_value: "Test"
example_name: "Test"
intent_name: "intent demo"
}

这里要注意的一点是dataSource状态变量是对象数组,比如

[{
add_entity: "yes"
entity_name: "entity demo"
entity_value: "Test"
example_name: "Test"
intent_name: "intent demo"
}]

我的预期输出低于

Entity Entity Value Operation
entity demo test delete icon
intent demo test delete icon

【问题讨论】:

    标签: reactjs antd


    【解决方案1】:

    如果你尝试一下会怎样

    setDataSource(prevDataSource => [...prevDataSource, values]);
    

    ?

    同理,删除一个项目:

    {
          title: "Operation",
          key: "operation",
          render: (record) => (
            <DeleteOutlined
              style={{ color: "red" }}
              onClick={() => {
                setDataSource(prevDataSource => prevDataSource.filter(item => item.entity_name !== record.entity_name //entity_name or whatever id the item has ))
              }}
            />
          ),
        },
    

    顺便说一句,如果您使用 typescript,请尽量避免使用 any。方法如下:

    import { Table } from 'antd';
    import { ColumnsType } from 'antd/es/table';
    
    interface User {
      key: number;
      name: string;
    }
    
    const columns: ColumnsType<User> = [
      {
        key: 'name',
        title: 'Name',
        dataIndex: 'name',
      },
    ];
    
    const data: User[] = [
      {
        key: 0,
        name: 'Jack',
      },
    ];
    
    export default () => (
      <>
        <Table<User> columns={columns} dataSource={data} />
        /* JSX style usage */
        <Table<User> dataSource={data}>
          <Table.Column<User> key="name" title="Name" dataIndex="name" />
        </Table>
      </>
    );
    

    【讨论】:

      猜你喜欢
      • 2020-12-04
      • 2018-08-30
      • 2019-03-16
      • 1970-01-01
      • 2020-02-10
      • 2019-10-11
      • 2021-07-01
      • 2021-07-29
      • 2021-05-20
      相关资源
      最近更新 更多