首页 > 解决方案 > 如何找出导致我的状态发生变化的原因?

问题描述

我正在呈现包含名称和大小的文件列表。此文件列表由父组件中的状态管理。在实际渲染文件的组件树的更深处,我使用Material-UI 的 Slide Transition 组件,以便在第一次渲染时,文件“滑动”到容器中。我还传递了一个 handleDelete 回调函数,这样当用户单击文件时,它就会从状态中删除。这是我的一些代码:

// Sample file list contained in parent component:

function File({ file, handleDelete }) {
  const [rendered, setRendered] = useState(true);

  useEffect(() => {
    if (!rendered) {
      console.log(file.name);
      handleDelete(file.name);
    }
  }, [rendered]);

  return (
    <Slide direction="left" in={rendered} mountOnEnter unmountOnExit>
      <div className={styles.File} onClick={() => setRendered(false)}>
        <p>{file.name}</p>
        <p>{file.size.toFixed(2)} MB</p>
      </div>
    </Slide>
  );
}

function FileList({ files, handleDelete }) {
  return (
    <React.Fragment>
      {files.map((file, i) => (
        <File key={i} file={file} handleDelete={handleDelete} />
      ))}
    </React.Fragment>
  );
}

然后我在父组件中有handleDelete回调函数:

  const handleDelete = (fileName) => {
    var newFiles = [];
    for (var i = 0; i < files.length; i++) {
      if (files[i].name != fileName) {
        newFiles.push(files[i]);
      }
    }
    handleSetFiles(newFiles);
  };

而handleSetFules 很简单:

  const handleSetFiles = (newFiles) => {
    setFiles(newFiles);
  };

File组件中的呈现状态控制每个文件是否应该滑入并在 true 时显示,或者在 false 时滑出。当我将文件添加到列表中时,一切都按预期呈现。当我单击文件时,我想将渲染状态设置为 false ,这将滑出文件并触发 useEffect 挂钩,然后从状态中删除文件。假设 FileList 组件根据以下传入的 prop 渲染每个 File:

const files = [
  {name: "file1", size: "1MB"},
  {name: "file2", size: "1MB"},
  {name: "file3", size: "1MB"},
  {name: "file4", size: "1MB"},
  {name: "file5", size: "1MB"},
];

如果我单击file1,会发生什么情况是file1的呈现状态设置为 false 并触发 useEffect 并从列表中删除并且不再显示。完全符合预期。但是,由于某种原因,下面的文件,即file2也将其渲染状态设置为 false 并且不显示,但它不会触发 useEffect 钩子,也不会调用handleDelete。当我使用 Chrome DevTools 时,我看到file1的File组件已被删除,但file2仍列出,其呈现状态为 false。文件的其余部分组件被显示并且它们的渲染状态仍然为真。我已经调试了好几个小时,但我无法弄清楚是什么导致我的状态发生变化。奇怪的是,如果我删除 useEffect 并单击file1file2的状态不会改变。有什么帮助吗?我尝试查看 Material-UI Slide 的文档,但找不到任何可以改变状态的地方......

标签: reactjsmaterial-ui

解决方案


所以,我相信你的问题的根源是幻灯片通过隐藏和显示一个组件来操作,而不是通过从 DOM 中删除它。因此,您应该通过翻转传递给in切换参数的“可见”标志来“删除”。

我不确定您是否将列表保存在某个商店中,但您不需要useEffect来获得您正在寻找的视觉效果。只需让您的handleDelete方法翻转“可见”标志即可。

这是 Material 的 Slider 演示中的代码,只是添加了额外的框,作为我的意思的演示: https ://codesandbox.io/s/material-demo-forked-10m4u?file=/demo.js


推荐阅读