SetState (...): Может обновлять только смонтированный или монтируемый компонент. Обычно это означает, что вы вызывали setState() на немонтированном компоненте. Это не-op
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() на unmounted компонент. Это не-op. Пожалуйста, проверьте код для undefinedкомпонент.
Я удаляюEventListener 'закончился' в componentWillUnmount
, но он не работает. потому что я добавляю this.setState({'time': remainTimeInfo});
в componentDidMount
.
Ответы
Ответ 1
Я решил это, назначив компоненту ref, а затем проверяя, существует ли ref перед установкой состояния:
myMethod(){
if (this.refs.myRef)
this.setState({myVar: true});
}
render() {
return (
<div ref="myRef">
{this.state.myVar}
</div>
);
}
Ответ 2
removeEventListener
имеет ту же подпись, что и addEventListener
. Все аргументы должны быть точно такими же, чтобы удалить слушателя.
var onEnded = () => {};
audioNode.addEventListener('ended', onEnded, false);
this.cleanup = () => {
audioNode.removeEventListener('ended', onEnded, false);
}
И в вызове componentWillUnmount this.cleanup()
.
Ответ 3
Изменить: isMounted
устарел и, вероятно, будет удален в более поздних версиях React. См. this, и это, isMounted является Антипаттерном.
Как указано в предупреждении, вы вызываете this.setState
на компонент, который был установлен, но с тех пор был размонтирован.
Чтобы убедиться, что ваш код в безопасности, вы можете его обернуть в
if (this.isMounted()) {
this.setState({'time': remainTimeInfo});
}
чтобы убедиться, что компонент все еще установлен.
Ответ 4
У меня была эта проблема раньше, и я решил ее в соответствии с React officail page isMounted является Антипаттерном.
Установите флаг isMounte свойства true в componentDidMount
и установите его false в componentWillUnmount
. Когда вы setState()
в своих обратных вызовах, сначала проверьте isMount
! Это работает для меня.
state = {
isMounted: false
}
componentDidMount() {
this.setState({isMounted: true})
}
componentWillUnmount(){
this.setState({isMounted: false})
}
Обратный вызов:
if (this.state.isMounted) {
this.setState({'time': remainTimeInfo});}
Ответ 5
Многие ответы в этой теме дают смысл использовать ссылки, но я думаю, что полный пример будет хорошим. Поскольку вы работаете с фактическим DOM node, используя прослушиватель событий и выходя из контекста React, ref следует рассматривать как стандартное решение. Вот полный пример:
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)
}
}
Ответ 6
addEventListener и removeEventListener, Callback не должен быть анонимным внутренним классом, и они должны иметь одинаковые параметры