No meu componente de reação, estou tentando implementar um spinner simples enquanto uma solicitação ajax está em andamento - estou usando o estado para armazenar o status de carregamento.
Por alguma razão, este trecho de código abaixo em meu componente React gera este erro
Só pode atualizar um componente montado ou de montagem. Isso geralmente significa que você chamou setState () em um componente não montado. Este é um ambiente autônomo. Verifique o código do componente indefinido.
Se eu me livrar da primeira chamada setState, o erro desaparecerá.
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>
);
}
A questão é por que estou recebendo este erro quando o componente já deveria estar montado (como está sendo chamado de componentDidMount). Eu pensei que era seguro definir o estado depois que o componente for montado?
fonte
this.state = { loading : null };
Respostas:
Sem ver a função de renderização é um pouco difícil. Embora já possa detectar algo que você deve fazer, toda vez que usar um intervalo, você terá que limpá-lo ao desmontar. Assim:
Como os retornos de chamada de sucesso e erro ainda podem ser chamados após a desmontagem, você pode usar a variável de intervalo para verificar se está montado.
Espero que isso ajude, forneça a função de renderização se isso não funcionar.
Felicidades
fonte
componentWillUnmount() { clearInterval(this.loadInterval); }
É não chamada a partir
componentDidMount
. SeucomponentDidMount
gera uma função de retorno de chamada que será executada na pilha do manipulador do cronômetro, não na pilha decomponentDidMount
. Aparentemente, no momento em que seu callback (this.loadSearches
) é executado, o componente já foi desmontado.Portanto, a resposta aceita irá protegê-lo. Se você estiver usando alguma outra API assíncrona que não permite o cancelamento de funções assíncronas (já enviadas para algum manipulador), você pode fazer o seguinte:
Isso eliminará a mensagem de erro que você relata em todos os casos, embora pareça que está varrendo coisas para debaixo do tapete, particularmente se sua API fornecer um recurso de cancelamento (como
setInterval
faz comclearInterval
).fonte
isMounted
é um antipadrão que o Facebook recomenda não usar: facebook.github.io/react/blog/2015/12/16/…Para quem precisa de outra opção, o método de retorno de chamada do atributo ref pode ser uma solução alternativa. O parâmetro de handleRef é a referência ao elemento div DOM.
Para obter informações detalhadas sobre refs e DOM: https://facebook.github.io/react/docs/refs-and-the-dom.html
fonte
fonte
Para a posteridade,
Este erro, em nosso caso, estava relacionado ao Reflux, callbacks, redirecionamentos e setState. Enviamos um setState para um retorno de chamada onDone, mas também enviamos um redirecionamento para o retorno de chamada onSuccess. Em caso de sucesso, nosso retorno de chamada onSuccess é executado antes de onDone . Isso causa um redirecionamento antes da tentativa de setState . Portanto, o erro, setState em um componente não montado.
Ação de armazenamento de refluxo:
Ligue antes de consertar:
Chamada após correção:
Mais
Em alguns casos, como o isMounted do React é "obsoleto / anti-padrão", adotamos o uso de uma variável _mounted e monitorando-a nós mesmos.
fonte
Compartilhe uma solução habilitada por ganchos de reação .
a mesma solução pode ser estendida para sempre que você quiser cancelar solicitações anteriores nas alterações de id de busca, caso contrário, haveria condições de corrida entre várias solicitações em voo (
this.setState
chamadas fora de serviço).isso funciona graças a fechamentos em javascript.
Em geral, a ideia acima estava próxima da abordagem makeCancelable recomendada pelo documento de reação, que afirma claramente
Crédito
https://juliangaramendy.dev/use-promise-subscription/
fonte