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');
}
Error:
Warnung: setState (...): Kann nur eine gemountete oder gemountete Komponente aktualisieren. Dies bedeutet normalerweise, dass Sie setState () für eine nicht gemountete Komponente aufgerufen haben. Dies ist ein No-Op. Bitte überprüfen Sie den Code für die undefinierte Komponente.
Ich entferneEventListener 'endete' in componentWillUnmount
, aber es funktioniert nicht. weil ich hinzufügen this.setState({'time': remainTimeInfo});
in componentDidMount
.
Antworten:
Ich habe dieses Problem gelöst, indem ich der Komponente eine Referenz zugewiesen und dann überprüft habe, ob die Referenz vorhanden ist, bevor ich den Status festgelegt habe:
myMethod(){ if (this.refs.myRef) this.setState({myVar: true}); } render() { return ( <div ref="myRef"> {this.state.myVar} </div> ); }
quelle
removeEventListener
hat die gleiche Signatur wieaddEventListener
. Alle Argumente müssen exakt gleich sein, damit der Listener entfernt wird.var onEnded = () => {}; audioNode.addEventListener('ended', onEnded, false); this.cleanup = () => { audioNode.removeEventListener('ended', onEnded, false); }
Und im Aufruf von componentWillUnmount
this.cleanup()
.quelle
Ich bin auf dieses Problem gestoßen, weil ich es
setState
anstelle desstate
Konstruktors verwendet habe.BEISPIEL
Ändern Sie den folgenden falschen Code
constructor(props) { super(props); this.setState({ key: '' }); }
zu
constructor(props) { super(props); this.state = { key: '' }; }
quelle
Bearbeiten :
isMounted
ist veraltet und wird wahrscheinlich in späteren Versionen von React entfernt. Sehen Sie dies und das, isMounted ist ein Antipattern .Wie in der Warnung angegeben, rufen Sie
this.setState
eine Komponente auf, die bereitgestellt wurde , aber seitdem nicht mehr bereitgestellt wurde.Um sicherzustellen, dass Ihr Code sicher ist, können Sie ihn einschließen
if (this.isMounted()) { this.setState({'time': remainTimeInfo}); }
um sicherzustellen, dass die Komponente noch montiert ist.
quelle
Ich habe das gleiche Problem, seit ich die neueste Reaktionsversion aktualisiert habe. Wie unten gelöst.
Mein Code war
async componentDidMount() { const { default: Component } = await importComponent(); Nprogress.done(); this.setState({ component: <Component {...this.props} /> }); }
Gewechselt zu
componentWillUnmount() { this.mounted = false; } async componentDidMount() { this.mounted = true; const { default: Component } = await importComponent(); if (this.mounted) { this.setState({ component: <Component {...this.props} /> }); } }
quelle
Ich hatte dieses Problem schon einmal und löste es laut der offiziellen React-Seite isMounted is a Antipattern .
Setzen Sie ein Eigenschaftsflag so
isMounted
, dass es wahr istcomponentDidMount
, und schalten Sie es falsch eincomponentWillUnmount
. Wenn SiesetState()
in Ihren Rückrufen, überprüfen SieisMounted
zuerst! Für mich geht das.state = { isMounted: false } componentDidMount() { this.setState({isMounted: true}) } componentWillUnmount(){ this.setState({isMounted: false}) }
zurückrufen:
if (this.state.isMounted) { this.setState({'time': remainTimeInfo});}
quelle
isMounted
um anzugeben. Sie sollten einfach verwendenthis.isMounted
. Dies hat nichts mit dem Reaktionszustand zu tun.this._isMounted
widerspricht es auch nicht den veraltetenisMounted()
offiziellen React-Dokumentationen und wirft keine Warnungen vor veralteten Warnungen aus .Viele der Antworten in diesem Thread haben den Sinn, Refs zu verwenden, aber ich denke, ein vollständiges Beispiel wäre gut. Da Sie auf einem tatsächlichen DOM-Knoten arbeiten, indem Sie den Ereignis-Listener verwenden und den React-Kontext verlassen, sollte ein Verweis als Standardlösung betrachtet werden. Hier ist ein vollständiges Beispiel:
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) } }
quelle
addEventListener und removeEventListener , Der Callback darf keine anonyme innere Klasse sein und sollte dieselben Parameter haben
quelle
Ich erhielt diese Warnung, als ich ein Popup (Bootstrap-Modal) für einen erfolgreichen / fehlgeschlagenen Rückruf einer Ajax-Anfrage anzeigen wollte. Außerdem funktionierte setState nicht und mein Popup-Modal wurde nicht angezeigt.
Unten war meine Situation-
<Component /> (Containing my Ajax function) <ChildComponent /> <GrandChildComponent /> (Containing my PopupModal, onSuccess callback)
Ich habe die Ajax-Funktion der Komponente von der Enkelkindkomponente aufgerufen und einen onSuccess-Rückruf (definiert in der Enkelkindkomponente) übergeben, bei dem der Status so eingestellt wurde, dass das Popup-Modal angezeigt wird.
Ich habe es geändert in -
<Component /> (Containing my Ajax function, PopupModal) <ChildComponent /> <GrandChildComponent />
Stattdessen habe ich setState (onSuccess Callback) aufgerufen, um das Popup-Modal in der Komponente (Ajax Callback) selbst anzuzeigen und das Problem zu lösen.
Im zweiten Fall: Die Komponente wurde zweimal gerendert (ich hatte bundle.js zweimal in HTML eingefügt).
quelle
Wenn Sie die Methode anstelle der anonymen Funktion im
audioNode.addEventListener
Rückruf benannt haben, sollte die Betreff-Warnung entfernt werden: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', this.callbackMethod ); } callBackMethod = () => { 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}); } }
Und ja, die benannte Methode wird sowieso benötigt, da
removeEventListener
sie nicht mit anonymen Rückrufen funktioniert, wie oben mehrmals erwähnt.quelle
componentWillUnmount
setState
,da das Flag isMounted veraltet ist
quelle