我的React组件中有以下两个生命周期方法,这是一个包含HTML <audio>
元素的音轨:
componentDidMount() {
const {track} = this.props;
this.refs.audio.src = track.getTrackUrl();
_.each(this.audioEvents, (callback, eventName) => {
this.refs.audio.addEventListener(eventName, callback.bind(this));
});
}
componentWillUnmount() {
_.each(this.audioEvents, (callback, eventName) => {
console.info(`Removed ${eventName} from ${this.props.track.name}`);
this.refs.audio.removeEventListener(eventName, callback.bind(this));
});
}
我可以从console.info
调用中看到所有事件都被删除了,但在导航离开此特定路径/页面时仍然会出现以下错误:
警告:setState(...):只能更新已安装或安装的组件。这通常意味着您在已卸载的组件上调用了setState()。这是一个无操作。请检查未定义组件的代码。
这种情况正在发生,因为即使我已经删除了所有事件处理程序,pause
回调仍然被解雇了:
pause() {
console.log('pause got fired for', this.props.track.name);
this.setState({playing: false});
},
我错过了什么?当组件卸载时,我试图做一个很好的清理,但出于某种原因,当我离开页面时(导致音频停止播放),pause
的事件处理程序仍然会触发。
答案 0 :(得分:3)
使用.bind
时,您可以创建该函数的新实例。所以当你这样做时:
this.refs.audio.addEventListener(eventName, callback.bind(this));
您将无法再删除该事件监听器,因为您没有抓住对callback.bind(this)
的引用。以下是解决问题的方法。
componentDidMount() {
const {track} = this.props;
this.refs.audio.src = track.getTrackUrl();
this.boundAudioEvents = _.mapValues(this.audioEvents, (callback, eventName) => {
const boundEvent = callback.bind(this)
this.refs.audio.addEventListener(eventName, boundEvent);
return boundEvent;
});
}
componentWillUnmount() {
_.each(this.boundAudioEvents, (callback, eventName) => {
console.info(`Removed ${eventName} from ${this.props.track.name}`);
this.refs.audio.removeEventListener(eventName, callback);
});
}