不使用最新状态的反应状态

React state not using the newest state

我正在尝试实现一个删除按钮,以使用 Ant Design UI 库从模式内的 table 中删除一行。但是,每当我调用 remove 函数时,即使我之前在初始项目之上添加了几个新项目,removeItem 组件内的 data 状态用法也不会更新,并且始终使用初始版本.每当我从 removeItem 组件内部输出 data 状态时,它总是从头开始显示 3 个项目。

但奇怪的是,如果我从 addItem 组件或 useEffect 挂钩中输出 data 内容,它会显示添加的新行。我无法弄清楚问题出在哪里。

编辑:link 到 codesandbox(编辑 barang -> 添加一些新项目 -> 删除新项目 -> 查看控制台日志)https://codesandbox.io/embed/wispy-meadow-czv6p?file=/src/App.js&codemirror=1

import { useState, useEffect } from "react";

const ModalBarang = (props) => {
  const dataSource = [
    {
      key: 1,
      code: "A123",
      name: "Barang 1",
      desc: "Description 1",
      qty: 30,
      price: 10000,
      total: 30 * 10000,
    },
    {
      key: 2,
      code: "B123",
      name: "Barang 2",
      desc: "Description 2",
      qty: 10,
      price: 20000,
      total: 10 * 20000,
    },
    {
      key: 3,
      code: "B123",
      name: "Barang 2",
      desc: "Description 2",
      qty: 10,
      price: 20000,
      total: 10 * 20000,
    },
  ];

  const tableColumns = [
    {
      title: "No",
      dataIndex: "key",
    },
    {
      title: "Kode Barang",
      dataIndex: "code",
      render: (text, _) => {
        return <Input value={text} />;
      },
    },
    {
      title: "Nama Barang",
      dataIndex: "name",
      render: (text, _) => {
        return <Input value={text} />;
      },
    },
    {
      title: "Deskripsi",
      dataIndex: "desc",
      render: (text, _) => {
        return <Input value={text} />;
      },
    },
    {
      title: "Qty",
      dataIndex: "qty",
      render: (text, _) => {
        return <Input value={text} />;
      },
    },
    {
      title: "Harga",
      dataIndex: "price",
      render: (text, _) => {
        return <Input value={text} />;
      },
    },
    {
      title: "Total",
      dataIndex: "total",
    },
    {
      title: "Hapus",
      dataIndex: "remove",
      render: (_, record) => {
        return (
          <Button
            type="default"
            danger="true"
            onClick={() => removeItem(record.key)}
          >
            Hapus Barang
          </Button>
        );
      },
    },
  ];

  const [columns, setColumns] = useState(tableColumns);
  const [data, setData] = useState(dataSource);

  const addItem = () => {
    const newRow = {
      key: data.length + 1,
      code: "",
      name: "",
      desc: "",
      qty: 0,
      price: 0,
      total: 0,
    };

    const newData = [...data, newRow];

    setData(newData);
  };

  const removeItem = (key) => {
    console.log(data); // ----> even after adding several items (addItem) the log only shows the initial values just like in datasource. E.g. initial items = 3, addItems 2 times so there should be 5 items. But when trying to remove item using this component, this console log only outputs the 3 initial items.

    const newItems = data.filter((item) => item.key !== key);

    setData(newItems);
  };

  return (
    <Modal
      title="Barang"
      visible={props.visible}
      onOk={props.onOk}
      onCancel={props.onCancel}
    >
      <Table dataSource={data} columns={columns} pagination={{ pageSize: 5 }} />
      <Button type="primary" htmlType="button" onClick={addItem}>
        Tambah Barang
      </Button>
    </Modal>
  );
};

export default ModalBarang;

当您更改对象时,React 不理解您应该这样做的更改:

setData([...newItems]);

您可以使用 ES6 扩展运算符克隆旧数组,从而生成新数组,如下所示 setData([...newItems])

这两种方法的区别在于调用它们的范围。当您使用复杂的 tablet 组件时,也许您应该参考您的库文档,因为 table 中的组件似乎以某种方式缓存。在不知道该组件如何工作的情况下,您可以将按钮更改为:

<Button
 type="default"
 danger="true"
 onClick={() => setItemToRemove(record.key) }
>
Hapus Barang
</Button>

然后你可以在你的父组件中做这样的事情:

const [itemToRemove, setItemToRemove] = useState();
      
useEffect(() => { 
   console.log(data)
   console.log(itemToRemove)}
   // ...
, [itemToRemove]) 

让我们尝试这样的事情:

const removeItem = (key) => {
  setData(prevData => prevData.filter(item => item.key !== key));
};