javascript - recargar - Reaccionar componente no volver a renderizar en cambio de estado
¿con qué método del ciclo de vida podemos capturar errores en nuestros componentes? (5)
En mi caso, estaba llamando a this.setState({})
correctamente, pero mi función no estaba vinculada a esto, por lo que no estaba funcionando. Agregando .bind(this)
a la llamada de función o haciendo this.foo = this.foo.bind(this)
en el constructor lo solucionó.
Tengo una clase React que va a una API para obtener contenido. He confirmado que los datos están regresando, pero no se están reproduciendo:
var DealsList = React.createClass({
getInitialState: function() {
return { deals: [] };
},
componentDidMount: function() {
this.loadDealsFromServer();
},
loadDealsFromServer: function() {
var newDeals = [];
chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
newDeals = deals;
});
this.setState({ deals: newDeals });
},
render: function() {
var dealNodes = this.state.deals.map(function(deal, index) {
return (
<Deal deal={deal} key={index} />
);
});
return (
<div className="deals">
<table>
<thead>
<tr>
<td>Name</td>
<td>Amount</td>
<td>Stage</td>
<td>Probability</td>
<td>Status</td>
<td>Exp. Close</td>
</tr>
</thead>
<tbody>
{dealNodes}
</tbody>
</table>
</div>
);
}
});
Sin embargo, si agrego un debugger
como el de abajo, se newDeals
y luego, una vez que continúo, veo los datos:
loadDealsFromServer: function() {
var newDeals = [];
chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
newDeals = deals;
});
debugger
this.setState({ deals: newDeals });
},
Esto es lo que está llamando lista de ofertas:
var Gmail = React.createClass({
render: function() {
return (
<div className="main">
<div className="panel">
<DealsList person={this.props.person} />
</div>
</div>
);
}
});
Esto se debe a que la respuesta de chrome.runtime.sendMessage
es asíncrona; Aquí está el orden de las operaciones:
var newDeals = [];
// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
// (3) sometime in the future, this function runs,
// but it''s too late
newDeals = deals;
});
// (2) this is called immediately, `newDeals` is an empty array
this.setState({ deals: newDeals });
Cuando pausa la secuencia de comandos con el depurador, le está dando a la extensión el tiempo para llamar a la devolución de llamada; para cuando continúas, los datos han llegado y parece funcionar.
Para solucionarlo, desea realizar la llamada a setState
después de que los datos regresen de la extensión de Chrome:
var newDeals = [];
// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
// (2) sometime in the future, this function runs
newDeals = deals;
// (3) now you can call `setState` with the data
this.setState({ deals: newDeals });
}.bind(this)); // Don''t forget to bind(this) (or use an arrow function)
[Editar]
Si esto no funciona para usted, consulte las otras respuestas a esta pregunta, que explican otras razones por las que su componente podría no estar actualizado.
Me gustaría añadir a esto el error de escritura enormemente simple, pero tan fácil de cometer:
this.state.something = ''changed'';
... y luego no entiendo por qué no está representando y buscando en Google y entrando en esta página, solo para darse cuenta de que debería haber escrito:
this.setState({something: ''changed''});
React solo activa una nueva representación si utiliza setState
para actualizar el estado.
Otro error tan fácil, que fue la fuente del problema para mí: escribí mi propio método shouldComponentUpdate
, que no verificaba el nuevo cambio de estado que había agregado.
Pasaba por el mismo problema en React-Native, donde la respuesta de la API y el rechazo no se estaban actualizando.
apiCall().then(function(resp) { this.setState({data: resp}) // wasn''t updating }
Resolví el problema cambiando la function
con la función de flecha
apiCall().then((resp) => {
this.setState({data: resp}) // rendering the view as expected
}
Para mí, era un tema vinculante. El uso de las funciones de flecha lo resolvió porque la función de flecha no crea su propio this
, siempre se limita a su contexto externo de donde proviene