subproperty - setstate object reactjs
setState(...): solo puede actualizar un componente montado o montado. Esto generalmente significa que llamó a setState() en un componente desmontado. Este es un no-op (11)
-
Cancele todas las operaciones asíncronas en
componentWillUnmount
-
Comprobar componente ya está desmontado cuando la llamada asincrónica establece
setState
,
dado que la bandera isMounted está en desuso
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:
Advertencia: setState (...): solo puede actualizar un componente montado o montado. Esto generalmente significa que llamó a setState () en un componente desmontado. Este es un no-op. Verifique el código del componente indefinido.
EliminoEventListener ''finalizó'' en
componentWillUnmount
, pero no funciona.
porque agrego
this.setState({''time'': remainTimeInfo});
en
componentDidMount
.
Encontré este problema porque usé
setState
lugar de
state
en el constructor.
EJEMPLO
Cambiar el siguiente código incorrecto
constructor(props) {
super(props);
this.setState({
key: ''''
});
}
a
constructor(props) {
super(props);
this.state = {
key: ''''
};
}
Me he enfrentado al mismo problema desde que actualicé la última versión de reacción. Resuelto como a continuación.
Mi código fue
async componentDidMount() {
const { default: Component } = await importComponent();
Nprogress.done();
this.setState({
component: <Component {...this.props} />
});
}
Cambiado a
componentWillUnmount() {
this.mounted = false;
}
async componentDidMount() {
this.mounted = true;
const { default: Component } = await importComponent();
if (this.mounted) {
this.setState({
component: <Component {...this.props} />
});
}
}
Muchas de las respuestas en este hilo captan el uso de referencias, pero creo que un buen ejemplo sería bueno. Dado que está operando en un nodo DOM real utilizando el detector de eventos y saliendo del contexto React, una referencia debe considerarse la solución estándar. Aquí hay un ejemplo completo:
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)
}
}
Recibí esta advertencia cuando quería mostrar una ventana emergente (modal de arranque) en la devolución de llamada de éxito / fracaso de la solicitud de Ajax. Además, setState no funcionaba y mi modal emergente no se mostraba.
Abajo estaba mi situación.
<Component /> (Containing my Ajax function)
<ChildComponent />
<GrandChildComponent /> (Containing my PopupModal, onSuccess callback)
Estaba llamando a la función ajax del componente desde el componente nieto pasando una devolución de llamada onSuccess (definida en el componente nieto) que estaba configurando el estado para mostrar modal emergente.
Lo cambié a ...
<Component /> (Containing my Ajax function, PopupModal)
<ChildComponent />
<GrandChildComponent />
En su lugar, llamé a setState (onSuccess Callback) para mostrar el popup modal en el componente (ajax callback) y resolvió el problema.
En el segundo caso: el componente se procesó dos veces (había incluido bundle.js dos veces en html).
Resolví esto asignando una referencia al componente y luego verificando si la referencia existe antes de establecer el estado:
myMethod(){
if (this.refs.myRef)
this.setState({myVar: true});
}
render() {
return (
<div ref="myRef">
{this.state.myVar}
</div>
);
}
Tener un método con nombre en lugar de la función anónima en la devolución de llamada de
audioNode.addEventListener
debería eliminar la advertencia de asunto:
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});
}
}
Y sí, el método con nombre es necesario de todos modos porque
removeEventListener
no funcionará con devoluciones de llamadas anónimas, como se mencionó anteriormente varias veces.
Tuve este problema antes, y lo resolví de acuerdo con la página oficial de React isMounted es un Antipatrón .
Establezca un
isMounted
propiedad
isMounted
para que sea verdadero en
componentDidMount
, y actívelo como falso en
componentWillUnmount
.
Cuando
setState()
en sus devoluciones de llamada, compruebe
isMounted
primero.
Esto funciona para mi.
state = {
isMounted: false
}
componentDidMount() {
this.setState({isMounted: true})
}
componentWillUnmount(){
this.setState({isMounted: false})
}
llamar de vuelta:
if (this.state.isMounted) {
this.setState({''time'': remainTimeInfo});}
addEventListener y removeEventListener, la devolución de llamada no debe ser una clase interna anónima y deben tener los mismos parámetros
removeEventListener
tiene la misma firma que
addEventListener
.
Todos los argumentos deben ser exactamente los mismos para que elimine el oyente.
var onEnded = () => {};
audioNode.addEventListener(''ended'', onEnded, false);
this.cleanup = () => {
audioNode.removeEventListener(''ended'', onEnded, false);
}
Y en componentWillUnmount llame a
this.cleanup()
.
Editar
:
isMounted
está en desuso y probablemente se eliminará en versiones posteriores de React.
Mira
this
y esto,
isMounted es un antipatrón
.
Como dice la advertencia, está llamando
this.setState
en un componente que
se
montó pero que desde entonces se ha desmontado.
Para asegurarse de que su código sea seguro, puede envolverlo
if (this.isMounted()) {
this.setState({''time'': remainTimeInfo});
}
para garantizar que el componente todavía esté montado.