为什么chrome.devtools.network.onRequestDone事件被触发数百次,我不删除它们,使用Preact?



我正在写一个chrome扩展。我使用的图书馆是Preact。这是我的状态和useEffect函数。

const [requests, setRequests] = useState([]);
useEffect(() => {
function processRequest(request) {
// if filter is unset
if (filter == "") {
setRequests((requests) => [...requests, request]);
} else {
// filter request url using wildcard
if (request.request.url.includes(filter)) {
setRequests((requests) => [...requests, request]);
}
}
}

chrome.devtools.network.onRequestFinished.addListener(processRequest);
return () => {

}
}, []);

然后我将requests绑定到html中的列表。

我构建了扩展,并尝试了一下。我发现页面的一次刷新会使列表长度达到20000。我知道实际上只有40个请求。我可以看到,有很多重复,通常一个请求被保存了数百次。

我意识到我没有删除事件侦听器,所以我更改了代码。

return () => {
chrome.devtools.network.onRequestFinished.removeListener(processRequest);
}

那就正常了。

我不太了解反应的机制,不知道发生了什么。你能解释一下为什么不移除侦听器会导致侦听器触发数百次吗?

useEffect将在每次组件渲染时被调用。

状态变量的改变将触发组件重新渲染。

每次调用useEffect时,它都会向chrome api添加另一个事件侦听器。因此,导致下一次请求完成时触发更多的侦听器。

监听器被调用->设置状态变量->组件重新渲染->useEffect增加了更多的监听器。然后下一个网络请求完成,导致所有侦听器被触发,然后进入一个新的循环。

useEffect返回的是清理函数。在本例中

return () => {
chrome.devtools.network.onRequestFinished.removeListener(processRequest);
}

该函数将在组件被卸载时调用,也就是生命周期结束时。

最新更新