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');
}
Erreur:
Attention: setState (...): ne peut mettre à jour qu'un montage ou un montage composant. Cela signifie généralement que vous avez appelé setState () sur un .mounted composant. C'est un no-op. S'il vous plaît vérifier le code pour le indéfini composant.
Je retireEventListener 'terminé' dans componentWillUnmount
, mais cela ne fonctionne pas. parce que j'ajoute this.setState({'time': remainTimeInfo});
dans componentDidMount
.
J'ai résolu ce problème en affectant un ref au composant, puis en vérifiant si le ref existe avant de définir l'état:
myMethod(){
if (this.refs.myRef)
this.setState({myVar: true});
}
render() {
return (
<div ref="myRef">
{this.state.myVar}
</div>
);
}
removeEventListener
a la même signature que addEventListener
. Tous les arguments doivent être exactement les mêmes pour supprimer l'auditeur.
var onEnded = () => {};
audioNode.addEventListener('ended', onEnded, false);
this.cleanup = () => {
audioNode.removeEventListener('ended', onEnded, false);
}
Et dans le composantWillUnmount, appelez this.cleanup()
.
J'ai rencontré ce problème car j'ai utilisé setState
au lieu de state
dans le constructeur.
EXEMPLE
Changer le code incorrect suivant
constructor(props) {
super(props);
this.setState({
key: ''
});
}
à
constructor(props) {
super(props);
this.state = {
key: ''
};
}
Edit: isMounted
est obsolète et sera probablement supprimé des versions ultérieures de React. Voir this et this, isMounted est un Antipattern .
Comme l'indique l'avertissement, vous appelez this.setState
sur un composant que was a monté mais a depuis été démonté.
Pour vous assurer que votre code est sécurisé, vous pouvez l'envelopper
if (this.isMounted()) {
this.setState({'time': remainTimeInfo});
}
pour vous assurer que le composant est toujours monté.
J'ai rencontré le même problème depuis que j'ai mis à jour la dernière version de Rea. Résolu comme ci-dessous.
Mon code était
async componentDidMount() {
const { default: Component } = await importComponent();
Nprogress.done();
this.setState({
component: <Component {...this.props} />
});
}
Changé en
componentWillUnmount() {
this.mounted = false;
}
async componentDidMount() {
this.mounted = true;
const { default: Component } = await importComponent();
if (this.mounted) {
this.setState({
component: <Component {...this.props} />
});
}
}
J'avais ce problème auparavant et je l'ai résolu conformément à la page officielle de React isMounted est un Antipattern .
Définissez un indicateur de propriété isMounted
sur true dans componentDidMount
et basculez-le sur false dans componentWillUnmount
. Lorsque vous setState()
dans vos rappels, vérifiez d'abord isMounted
! Ça marche pour moi.
state = {
isMounted: false
}
componentDidMount() {
this.setState({isMounted: true})
}
componentWillUnmount(){
this.setState({isMounted: false})
}
rappeler:
if (this.state.isMounted) {
this.setState({'time': remainTimeInfo});}
Beaucoup de réponses dans ce fil de discussion ont le sens d'utiliser des références, mais je pense qu'un exemple complet serait bien. Puisque vous travaillez sur un nœud DOM réel en utilisant l'écouteur d'événements et en sortant du contexte React, une référence doit être considérée comme la solution standard. Voici un exemple complet:
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)
}
}
addEventListener et removeEventListener le rappel ne doit pas être une classe interne anonyme, et ils doivent avoir les mêmes paramètres
Avoir nommé la méthode à la place de la fonction anonyme dans le rappel de audioNode.addEventListener
devrait éliminer l'avertissement du sujet:
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});
}
}
Et oui, la méthode nommée est de toute façon nécessaire car removeEventListener
ne fonctionnera pas avec les rappels anonymes, comme mentionné ci-dessus à plusieurs reprises.
Je recevais cet avertissement lorsque je voulais afficher une fenêtre contextuelle (modal bootstrap) lors du rappel de réussite/échec de la demande Ajax. De plus, setState ne fonctionnait pas et ma modale popup n'était pas affichée.
Ci-dessous ma situation
<Component /> (Containing my Ajax function)
<ChildComponent />
<GrandChildComponent /> (Containing my PopupModal, onSuccess callback)
J'appelais la fonction ajax du composant petitchild en passant un callback onSuccess (défini dans le composant petitchild) qui configurait state pour afficher le mode modal.
Je l'ai changé pour -
<Component /> (Containing my Ajax function, PopupModal)
<ChildComponent />
<GrandChildComponent />
Au lieu de cela, j'ai appelé setState (onSuccess Callback) pour afficher le composant modal dans le composant (rappel ajax) lui-même et le problème résolu.
Dans le second cas: le composant était rendu deux fois (j'avais inclus bundle.js deux fois en html).
componentWillUnmount
setState
,