我正在写一个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);
}
该函数将在组件被卸载时调用,也就是生命周期结束时。