Atualmente, estou acompanhando a documentação do React JS e encontrei um problema com os limites de erro que não estavam funcionando conforme o esperado. Tentei replicar o exemplo mostrado no CodePen fornecido pelos documentos e alguns outros exemplos simples que encontrei na internet, no entanto, ele não está funcionando da mesma forma que na demonstração e estou com dificuldades. para entender o porquê.
O problema exato é que o erro está sendo gerado duas vezes porque o componente BuggyCounter é processado por um tempo extra. Eu não entendo por que o componente está renderizando uma segunda vez.
Por favor, dê uma olhada neste exemplo mínimo.
import React, { Component } from 'react';
function App() {
return (
<ErrorHandler>
<BuggyCounter />
</ErrorHandler>
);
}
class ErrorHandler extends Component {
constructor(props) {
super(props);
this.state = {
error: false,
errorInfo: null
}
}
componentDidCatch(error, errorInfo) {
this.setState({ error, errorInfo });
}
render() {
console.log('rendering ErrorHandler. ' + (this.state.error ? "error" : "no error"));
if(this.state.error) {
return <p>Error</p>
}
return this.props.children;
}
}
class BuggyCounter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
}
handleClick = () => {
this.setState(({ counter }) => ({
counter: counter + 1
}));
};
render() {
console.log('rendering BuggyCounter. count: ' + this.state.counter);
if (this.state.counter === 5) {
throw new Error('I crashed!');
}
return <h1 onClick={this.handleClick}>{this.state.counter}</h1>
}
}
export default App;
O componente BuggyCounter está sendo substituído pela <p>
tag que gera "Erro" (que é o efeito desejado), mas apenas por um momento. Imediatamente depois disso, a página de erro padrão está sendo mostrada, anulando a finalidade dos limites de erro.
Aqui está o meu console:
Agradecemos qualquer informação que você possa fornecer sobre este tópico.
Resolução temporária:
Não é uma resposta para minha pergunta, mas uma maneira de impedir a renderização redundante é lançar o erro em componentDidUpdate
vez de render
.
render() {
console.log('rendering BuggyCounter. count: ' + this.state.counter);
return <h1 onClick={this.handleClick}>{this.state.counter}</h1>
}
componentDidUpdate() {
if(this.state.counter === 5)
throw new Error('I crashed');
}
componentDidCatch
, verá que ele lança o erro duas vezes, mas apenas passacomponenDidCatch
uma vez.Respostas:
Edição 2:
Bem, o problema está na versão react
16.12.0
, se você mudar para16.0.0
, ele não será renderizado duas vezes mais. Você pode testar isso nesta caixa de código , alterando a versão de reação.Esse é um bom problema para adicionar no react github.
Provavelmente é algo internamente no código principal do react. Portanto, dependendo da sua versão, ela será renderizada duas ou apenas uma vez.
Editar:
Por que o componente é renderizado novamente? Nenhuma idéia.
Mas, a página de erro é mostrada apenas no modo de desenvolvimento , portanto você
componentDidCatch
está trabalhando.Resposta antiga / ruim
A
only for a moment
parte não é verdadeira. A página de erro é apenas para desenvolvimento, se você a executar no modo de produção, ela não será mostrada.E como você pode ver no meu exemplo , se você fechar a página de erro, verá o componente de erro.
Isso é explicado nesta resposta .
Portanto, na versão demo fornecida pelo react docs, ela não mostra a página de erro devido à sua configuração, e não ao código. Seu código está funcionando bem, basta fechar a página de erro e ver os resultados.
fonte
BuggyCounter
deve estar sendo renderizado duas vezes quando,state.counter === 5
porque o log mostra "Rendering BuggyCounter. Count: 5" duas vezes. Eu acredito que você explicou por queErrorHandler
está sendo processado um tempo extra.BuggyCounter
está executando uma renderização adicional após gerar um erro.componentDidCatch
. Alterações de estado renderizarão novamente seu componente.ErrorHandler
está sendo renderizado novamente. Essa não é a minha pergunta. Se você olhar para o log,BuggyCounter
está sendo renderizado um tempo extra antes deErrorHandler
ser renderizado novamente devido a alterações de estado.