reactjs - 如何找出导致我的状态发生变化的原因?
问题描述
我正在呈现包含名称和大小的文件列表。此文件列表由父组件中的状态管理。在实际渲染文件的组件树的更深处,我使用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 并单击file1,file2的状态不会改变。有什么帮助吗?我尝试查看 Material-UI Slide 的文档,但找不到任何可以改变状态的地方......
解决方案
所以,我相信你的问题的根源是幻灯片通过隐藏和显示一个组件来操作,而不是通过从 DOM 中删除它。因此,您应该通过翻转传递给in
切换参数的“可见”标志来“删除”。
我不确定您是否将列表保存在某个商店中,但您不需要useEffect
来获得您正在寻找的视觉效果。只需让您的handleDelete
方法翻转“可见”标志即可。
这是 Material 的 Slider 演示中的代码,只是添加了额外的框,作为我的意思的演示: https ://codesandbox.io/s/material-demo-forked-10m4u?file=/demo.js
推荐阅读
- reactjs - 是否可以使用对象类型定义来构造新的数组/元组类型?
- python - 是否可以使用单个 django ORM 查询来实现此功能?
- heroku - Heroku dyno 重启后保留数据
- c# - 检查流利的 EF Core 配置中是否存在属性 ID
- istio - Maistra 和 Istio 是什么关系
- javascript - Svelte - 如何使数据不反应?
- laravel - 我正在使用 Laravel + vue 通过 Blade 将变量传递给 vue 但它不显示
- r - 如何在捕获行为的虚拟变量从 1 切换到 0 之前和之后删除变量
- objective-c - 当有一个子窗口时,NSView 事件会在几秒钟后随机停止
- c# - 使用空间感知网格观察器 MHL2 从对象创建网格