En mi componente de reacción, estoy tratando de implementar un spinner simple mientras una solicitud ajax está en progreso; estoy usando el estado para almacenar el estado de carga.
Por alguna razón, este fragmento de código a continuación en mi componente React arroja este error
Solo se puede actualizar un componente montado o de montaje. Por lo general, esto significa que llamó a setState () en un componente desmontado. Esta es una operación no operativa. Compruebe el código del componente indefinido.
Si me deshago de la primera llamada setState, el error desaparece.
constructor(props) {
super(props);
this.loadSearches = this.loadSearches.bind(this);
this.state = {
loading: false
}
}
loadSearches() {
this.setState({
loading: true,
searches: []
});
console.log('Loading Searches..');
$.ajax({
url: this.props.source + '?projectId=' + this.props.projectId,
dataType: 'json',
crossDomain: true,
success: function(data) {
this.setState({
loading: false
});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
this.setState({
loading: false
});
}.bind(this)
});
}
componentDidMount() {
setInterval(this.loadSearches, this.props.pollInterval);
}
render() {
let searches = this.state.searches || [];
return (<div>
<Table striped bordered condensed hover>
<thead>
<tr>
<th>Name</th>
<th>Submit Date</th>
<th>Dataset & Datatype</th>
<th>Results</th>
<th>Last Downloaded</th>
</tr>
</thead>
{
searches.map(function(search) {
let createdDate = moment(search.createdDate, 'X').format("YYYY-MM-DD");
let downloadedDate = moment(search.downloadedDate, 'X').format("YYYY-MM-DD");
let records = 0;
let status = search.status ? search.status.toLowerCase() : ''
return (
<tbody key={search.id}>
<tr>
<td>{search.name}</td>
<td>{createdDate}</td>
<td>{search.dataset}</td>
<td>{records}</td>
<td>{downloadedDate}</td>
</tr>
</tbody>
);
}
</Table >
</div>
);
}
La pregunta es por qué recibo este error cuando el componente ya debería estar montado (ya que se llama desde componentDidMount). Pensé que era seguro establecer el estado una vez que el componente está montado.
fuente
this.state = { loading : null };
Respuestas:
Sin ver la función de renderizado es un poco complicado. Aunque ya puede detectar algo que debe hacer, cada vez que usa un intervalo, debe borrarlo al desmontar. Entonces:
Dado que esas devoluciones de llamada de éxito y error aún se pueden llamar después del desmontaje, puede usar la variable de intervalo para verificar si está montada.
Espero que esto ayude, proporcione la función de renderizado si esto no funciona.
Salud
fuente
componentWillUnmount() { clearInterval(this.loadInterval); }
Se no llamó desde
componentDidMount
. SucomponentDidMount
genera una función de devolución de llamada que se ejecutará en la pila del controlador del temporizador, no en la pila decomponentDidMount
. Aparentemente, para cuandothis.loadSearches
se ejecuta su callback ( ), el componente se ha desmontado.Entonces la respuesta aceptada lo protegerá. Si está utilizando alguna otra API asincrónica que no le permite cancelar funciones asincrónicas (ya enviadas a algún controlador), puede hacer lo siguiente:
Esto eliminará el mensaje de error que informa en todos los casos, aunque se siente como si estuviera escondiendo cosas debajo de la alfombra, particularmente si su API proporciona una capacidad de cancelación (como lo
setInterval
hace conclearInterval
).fuente
isMounted
es un antipatrón que Facebook aconseja no utilizar: facebook.github.io/react/blog/2015/12/16/…Para quién necesita otra opción, el método de devolución de llamada del atributo ref puede ser una solución. El parámetro de handleRef es la referencia al elemento div DOM.
Para obtener información detallada sobre referencias y DOM: https://facebook.github.io/react/docs/refs-and-the-dom.html
fuente
fuente
Para la posteridad,
Este error, en nuestro caso, estaba relacionado con Reflux, callbacks, redirects y setState. Enviamos un setState a una devolución de llamada onDone, pero también enviamos una redirección a la devolución de llamada onSuccess. En caso de éxito, nuestra devolución de llamada onSuccess se ejecuta antes que onDone . Esto provoca una redirección antes del intento setState . Por lo tanto, el error setState en un componente desmontado.
Acción de almacenamiento de reflujo:
Llame antes de arreglar:
Llamar después de arreglar:
Más
En algunos casos, dado que React's isMounted está "obsoleto / anti-patrón", hemos adoptado el uso de una variable _mounted y la monitoreamos nosotros mismos.
fuente
Comparta una solución habilitada por react hooks .
la misma solución puede extenderse siempre que desee cancelar solicitudes anteriores sobre cambios de identificación de búsqueda; de lo contrario, habría condiciones de carrera entre múltiples solicitudes en vuelo (
this.setState
llamadas fuera de servicio).esto funciona gracias a cierres en javascript.
En general, la idea anterior estaba cerca del enfoque makeCancelable recomendado por react doc, que establece claramente
Crédito
https://juliangaramendy.dev/use-promise-subscription/
fuente