【发布时间】:2026-01-04 03:20:03
【问题描述】:
编辑 这似乎是由于 React 中的一个问题,并在未来的版本中得到修复。 https://github.com/facebook/react/issues/18066
鉴于 react 中的表格显示来自 API 的数据,可以使用全新的信息进行刷新,我观察到分离的 DOM 节点泄漏(观察绿色数字):
Here is the code executed in the gif(代码包含在下面以供后代使用)。 要查看泄漏,请转到full page,打开 chrome 开发工具,查看“性能监视器”选项卡并快速单击“重新生成”按钮,如 gif 所示。
In this codesandbox,节点不是在循环中生成的,泄漏确实不会发生。
唯一的区别是 jsx 中的 {rows} 数组。令人困惑的部分是 {rows} 不是全局变量,所以我看不出它如何防止旧节点被 GC。
为什么使用局部变量 rows 会导致分离的 DOM 节点泄漏?
注意:DOM 节点似乎稳定在 21,000,但无论如何不应该有那么多节点,因为您可以看到它在第一个表生成后从 7,000 开始。在我的真实应用程序中,这些分离的节点甚至通过导航(使用反应路由器)仍然存在,这让我相信这是一个实际的泄漏,而不仅仅是等待 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>
);
}
【问题讨论】:
-
你在本地试过吗?我想知道这是否可能是由于代码沙箱上的某种无限循环保护引起的?
-
@JayB 是的,问题首先发生在本地
标签: javascript reactjs memory-leaks react-hooks