setState(…):只能更新已安装或已安装的组件。 这通常意味着您在卸载的组件上调用了setState()。 这是一个没有操作

componentDidMount(prevProps, prevState, prevContext) { let [audioNode, songLen] = [this.refs.audio, List.length-1]; audioNode.addEventListener('ended', () => { this._endedPlay(songLen, () => { this._currSong(this.state.songIndex); this._Play(audioNode); }); }); audioNode.addEventListener('timeupdate', () => { let [remainTime, remainTimeMin, remainTimeSec, remainTimeInfo] = []; if(!isNaN(audioNode.duration)) { remainTime = audioNode.duration - audioNode.currentTime; remainTimeMin = parseInt(remainTime/60); // 剩余分 remainTimeSec = parseInt(remainTime%60); // 剩余秒 if(remainTimeSec < 10) { remainTimeSec = '0'+remainTimeSec; } remainTimeInfo = remainTimeMin + ':' + remainTimeSec; this.setState({'time': remainTimeInfo}); } }); } componentWillUnmount () { let audio = this.refs.audio; audio.removeEventListener('timeupdate'); audio.removeEventListener('ended'); } 

错误:

警告:setState(…):只能更新已安装或已安装的组件。 这通常意味着您在卸载的组件上调用了setState()。 这是一个没有操作。 请检查未定义组件的代码。

我removeEventListener'结束'在componentWillUnmount ,但它不工作。 因为我加了this.setState({'time': remainTimeInfo});componentDidMount

我解决了这个问题,通过给组件分配ref ,然后在设置状态之前检查ref是否存在:

 myMethod(){ if (this.refs.myRef) this.setState({myVar: true}); } render() { return ( <div ref="myRef"> {this.state.myVar} </div> ); } 

removeEventListeneraddEventListener具有相同的签名。 所有参数必须完全相同才能删除侦听器。

 var onEnded = () => {}; audioNode.addEventListener('ended', onEnded, false); this.cleanup = () => { audioNode.removeEventListener('ended', onEnded, false); } 

并在componentWillUnmount中调用this.cleanup()

编辑isMounted已被弃用,可能会在更高版本的React中被删除。 看到这个 ,这是isMounted是一个反模式 。


正如警告所述,您正在调用this.setState的一个组件挂载,但从那时起已被卸载。

为了确保你的代码是安全的,你可以包装它

 if (this.isMounted()) { this.setState({'time': remainTimeInfo}); } 

确保组件仍然安装。

之前我有这个问题,并且根据React officail page isMounted是一个Antipattern来解决它。

componentDidMount设置属性isMounte标志为true,并在componentWillUnmount中将其切换为false。 当你在你的callback中设置状态setState()时,首先检查isMount ! 这个对我有用。

 state = { isMounted: false } componentDidMount() { this.setState({isMounted: true}) } componentWillUnmount(){ this.setState({isMounted: false}) } 

回电话:

 if (this.state.isMounted) { this.setState({'time': remainTimeInfo});} 

在这个线程中的很多答案得到使用refs的点,但我认为一个完整的例子会很好。 由于您使用事件侦听器并在React上下文之外操作实际的DOM节点,因此ref应该被视为标准解决scheme。 这是一个完整的例子:

 class someComponent extends Component { constructor(props) { super(props) this.node = null } render() { return ( <div ref={node => { this.node = node }}>Content</div> ) } handleEvent(event) { if (this.node) { this.setState({...}) } } componentDidMount() { //as soon as render completes, the node will be registered. const handleEvent = this.handleEvent.bind(this) this.node.addEventListener('click', handleEvent) } componentWillUnmount() { const handleEvent = this.handleEvent.bind(this) this.node.removeEventListener('click', handleEvent) } }