gpt4 book ai didi

javascript - React 中分离的 DOM 节点内存泄漏

转载 作者:行者123 更新时间:2023-11-28 16:48:49 31 4
gpt4 key购买 nike

编辑看来这是由于 React 中的一个问题造成的,并将在未来的版本中修复。 https://github.com/facebook/react/issues/18066

<小时/>

给定 React 中的一个表,该表显示来自 API 的数据,可以用全新的信息刷新,我观察到分离的 DOM 节点泄漏(观察绿色数字):

Gif of memory leak

Here is the code executed in the gif (下面包含代码以供后代使用)。要查看泄漏情况,请转到 full page ,打开 Chrome 开发工具,查看“性能监视器”选项卡,然后快速单击“Regen”按钮,如 gif 所示。

In this codesandbox ,如果节点不是在循环中生成的,则不会发生泄漏。

唯一的区别是 jsx 中的 {rows} 数组。令人困惑的部分是 {rows} 不是全局变量,所以我不知道它如何防止旧节点被 GC'd。

为什么使用局部变量rows会导致分离的DOM节点泄漏?

注意:DOM 节点似乎稳定在 21,000 个,但无论如何都不应该有那么多节点,因为您可以看到在第一个表生成后它从 7,000 个开始。在我的真实应用程序中,这些分离的节点甚至通过导航(使用 react 路由器)仍然存在,这让我相信这是一个真正的泄漏,而不仅仅是等待 GC 的节点。

<小时/>

模拟泄漏的完整代码:

import React, { useState } from "react";

export default function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<button onClick={() => setCount(prev => prev + 1)}>Regen</button>
<FTable count={count} />
</div>
);
}

function Cell() {
const num = Math.floor(Math.random() * 100);
return <td>{num}</td>;
}
function FTable(props) {
const { count } = props;
const rows = [];
if (count > 0) {
for (let i = 0; i < 1000; i++) {
rows.push(
// Use a different key for each time the
// table is regenerated to simulate a new API
// call bringing in new data
<tr key={`${i} ${count}`}>
<Cell row={i} />
<Cell row={i} />
<Cell row={i} />
</tr>
);
}
}
return (
<div>
<table>
<tbody>{rows}</tbody>
</table>
</div>
);
}

最佳答案

起初,我认为这是 Hooks API 的一个错误。因为如果你替换 <FTable count={count} /><FTable count={1} />然后 bug 就会消失。但这不是解决方案。

有一个关于 unexpected behavior 的问题与 Hook 。但在这种情况下,JS 堆大小而不是 DOM 节点在增长。

然后我想“好吧,我会用类组件尝试这个案例”,然后我做了 this demo 。同样的问题仍然存在。好吧,如果这个问题是在 16.3 版本中和 Hooks 一起引入的呢?但不是。同样的问题exist in 16.0 .

然后我意识到。关键问题是所有这些案例之间有什么共同点?关键!

Documentation says :

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings.

事实证明,如果每个渲染上的键都是唯一的,React 不会“垃圾收集”旧节点(好吧,在本例中)。这就是为什么如果您使用 <tr key={i}>那么一切都很好,因为 React “重写” 这些节点,并且当您使用 ${i * count} 时或${i} ${count}“无论每次渲染都是唯一的”,那么节点将位于内存中。过了某个时间点,旧节点将被新节点替换,但我猜这是与浏览器相关的行为,而不是 React。但我不是 react 专家,我不知道这种情况在哪里以及如何发生。

此时,您可以在 GitHub 上创建问题并了解此问题。

关于javascript - React 中分离的 DOM 节点内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60197254/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com