Atualização em abril de 2020:
o problema parece ter sido corrigido no React 16.13.1 mais recente; veja este exemplo de sandbox . Obrigado a @abernier por apontar isso.
Fiz algumas pesquisas e descobri uma diferença importante: o
React não processa erros dos métodos de ciclo de vida assíncronos.
Então, se você escrever algo como isto:
componentDidMount()
{
throw new Error('I crashed!');
}
seu erro será detectado pelo limite do erro e você poderá processá-lo e exibir uma mensagem normal .
Se mudarmos o código assim:
async componentDidMount()
{
throw new Error('I crashed!');
}
que é equivalente a isso:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
então o seu erro será silenciosamente engolido . Que vergonha, reagir ...
Então, como processamos erros? A única maneira parece ser uma captura explícita como esta:
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
ou assim:
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
Se ainda queremos que nosso erro atinja o limite de erro, posso pensar no seguinte truque:
- Capture o erro, faça com que o manipulador de erros altere o estado do componente
- Se o estado indicar um erro, jogue-o no
render
método
Exemplo:
class BuggyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { error: null };
}
buggyAsyncfunction(){ return Promise.reject(new Error('I crashed async!'));}
async componentDidMount() {
try
{
await this.buggyAsyncfunction();
}
catch(error)
{
this.setState({error: error});
}
}
render() {
if(this.state.error)
throw this.state.error;
return <h1>I am OK</h1>;
}
}