Aggiornamento aprile 2020:
il problema sembra essere stato risolto nell'ultimo React 16.13.1, vedi questo esempio sandbox . Grazie a @abernier per averlo segnalato.
Ho fatto alcune ricerche e ho trovato un'importante differenza:
React non elabora errori dai metodi del ciclo di vita asincrono.
Quindi, se scrivi qualcosa del genere:
componentDidMount()
{
throw new Error('I crashed!');
}
quindi il tuo errore verrà colto dall'errore di lavanderia e potrai elaborarlo e visualizzare un messaggio grazioso.
Se cambiamo il codice in questo modo:
async componentDidMount()
{
throw new Error('I crashed!');
}
che equivale a questo:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
quindi il tuo errore verrà ingerito silenziosamente . Vergogna, reagisci ...
Quindi, come possiamo elaborare gli errori di? L'unico modo sembra essere la cattura esplicita in questo modo:
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
o in questo modo:
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
Se vogliamo ancora che il nostro errore raggiunga il limite dell'errore, posso pensare al seguente trucco:
- Cattura l'errore, fai in modo che il gestore errori cambi lo stato del componente
- Se lo stato indica un errore, gettalo dal
rendermetodo
Esempio:
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>;
}
}