无法从子组件更新父级的状态

Cannot update parent's state from child component

我有一个父组件,其中包含用于构建 table 行的数据。子组件呈现实际 table。每行都应该删除table,所以我在父组件中创建了一个函数来更新它的状态,并将它传递给子组件,这样它就可以在点击按钮时被调用。

即使 setter 函数被触发,状态实际上并没有改变。 table 不会重新呈现,并且不会触发 files 作为依赖项的 useEffect

我不明白为什么会这样,here是codesandbox中重现的问题。如果有人能帮助解决这个问题,我将非常高兴。

编辑:我在此处添加代码,因为链接可能会随着时间的推移而中断,正如@UmerAbbas 指出的那样。

// App.js
import { useEffect, useState } from "react";
import Table from "./Table";

export default function App() {
  const [files, setFiles] = useState({
    "mario.jpg": {
      name: "mario.jpg",
      size: 1234
    },
    "luigi.mkv": {
      name: "luigi.mkv",
      size: 1234567
    }
  });
  const [rows, setRows] = useState([]);

  useEffect(() => {
    console.log("files have changed");
    setRows([]);
    const filesKeys = Object.keys(files);
    for (const filename of filesKeys) {
      setRows((prevState) => [
        ...prevState,
        { filename, size: files[filename].size }
      ]);
    }
  }, [files]);

  const handleDelete = (file) => {
    console.log(file);
    const _files = files;
    delete _files[file];
    console.log("Setting files");
    setFiles(_files);
    console.log("files set");
  };

  return (
    <div className="App">
      <Table rows={rows} handleDelete={handleDelete} />
    </div>
  );
}

// Table.jsx
export default function Table({ rows, handleDelete }) {
  return (
    <table style={{ width: "100%" }}>
      <tr>
        <th>Name</th>
        <th>Size</th>
        <th></th>
      </tr>
      {rows.map((row) => {
        return (
          <tr key={row.filename}>
            <td>{row.filename}</td>
            <td>{row.size}</td>
            <td>
              <button onClick={() => handleDelete(row.filename)}>Delete</button>
            </td>
          </tr>
        );
      })}
    </table>
  );
}

您需要使用set state功能版本

const handleDelete = (file) => {
  setFiles((prev) => {
    const { [file]: fileName, ...rest } = prev;
    return rest;
  });
  console.log("files set");
};

尝试像这样复制一个元素:

  const handleDelete = (file) => {
    const _files = { ...files };  // like this
    delete _files[file];
    setFiles(_files);
  };

sandbox link

您的问题实际上没有您想象的那么严重。在您的沙箱中,您似乎试图通过不在第 32 行创建 files 的副本来直接更新状态。如果您在对对象进行编辑之前创建浅表副本,则您的沙箱可以正常工作:

const _files = { ...files };

有关详细信息,请参阅 here(请注意,尽管文档适用于 class-based 组件,但原则也适用于功能组件)。