当弹出窗口关闭时,如何删除扩展弹出窗口(React组件)的侦听器



我有一个使用react(遗留代码(构建的扩展,我一直在跟踪一个最终陷入困境的bug,但我无法修复。

当点击扩展的图标(在浏览器栏中(时,会创建一个reactComponent,并在其componentDidMount():中添加一个监听器

async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// code including await background_object.doSomething();
...
// add event (eventemitter3 is used for the event management)
background_object.event.on('onMusic', this.dance);
...
}
async dance() {
this.setState({
'music': true,
})
}

然而,一旦Component消失,我就不知道如何删除侦听器,例如单击浏览器中的其他位置。我以为componentWillUnmount是我想要的,但它从来没有被称为:

componentWillUnmount(){
// this is never called!!!
background_object.event.removeListener('onDance', this.dance);
}

问题是,每次我打开(和关闭(扩展弹出窗口时,都会向background_object添加一个新事件,因此dance()会被调用多次(与我打开和关闭弹出窗口的次数一样多(。

目前,我使用了once而不是on:

async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// code including await background_object.doSomething();
...
// add event (eventemitter3 is used for the event management)
background_object.event.once('onMusic', this.dance);
...
}
async dance() {
// add the event again in case onMusic is called again
background_object.event.once('onMusic', this.dance);
this.setState({
'music': true,
})
}

通过这种方式,至少,它只被调用一次。但是,我担心我的组件被创建了多次,并且占用了浏览器中的内存。

我如何才能确保组件确实被销毁?如何检测弹出窗口何时关闭以删除事件?

可以使用chrome.runtime.onConnect(感谢@wOxxOm(:

  1. 在React组件的构造函数中打开一个连接:
constructor(props){
super(props)
this.state = {
dance: false,
}
...
var port = this.xbrowser.runtime.connect();
...
}
  1. 在react组件的componentDidMount中添加事件
async componentDidMount(){
...
// an object from the background is retrieved
let background_object = this.props.getBackgroundObject();
...
// add event (eventemitter3 is used for the event management)
background_object.event.on('onMusic', this.dance);
...
}
async dance() {
this.setState({
'music': true,
})
}
  1. 在后台的某个位置(例如background.js(监听到浏览器的连接,并在连接丢失时删除事件:
chrome.runtime.onConnect.addListener(function (externalPort) {
externalPort.onDisconnect.addListener(function () {
let background_object = this.props.getBackgroundObject();
background_object.event.removeListener('onSend'); 
})
})

在我看来,这不是很优雅,但它正在发挥作用。

最新更新