Actualización de abril de 2020:
el problema parece haberse solucionado en la última Reacción 16.13.1, consulte este ejemplo de sandbox . Gracias a @abernier por señalar esto.
He investigado un poco y he encontrado una diferencia importante:
React no procesa errores de los métodos asíncronos del ciclo de vida.
Entonces, si escribes algo como esto:
componentDidMount()
{
throw new Error('I crashed!');
}
entonces su error será detectado por el límite de errores , y puede procesarlo y mostrar un mensaje elegante.
Si cambiamos el código así:
async componentDidMount()
{
throw new Error('I crashed!');
}
que es equivalente a esto:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
entonces su error será tragado en silencio . La culpa es tuya, reacciona ...
Entonces, ¿cómo procesamos los errores que? La única forma parece ser una captura explícita como esta:
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
o así:
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
Si aún queremos que nuestro error alcance el límite de error, puedo pensar en el siguiente truco:
- Detecte el error, haga que el controlador de errores cambie el estado del componente
- Si el estado indica un error, tírelo desde el
render
método
Ejemplo:
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>;
}
}