Aktualizacja z kwietnia 2020 r .:
Wydaje się, że problem został rozwiązany w najnowszej wersji React 16.13.1, zobacz ten przykład piaskownicy . Dzięki @abernier za wskazanie tego.
Przeprowadziłem kilka badań i znalazłem jedną ważną różnicę:
React nie przetwarza błędów z asynchronicznych metod cyklu życia.
Więc jeśli napiszesz coś takiego:
componentDidMount()
{
throw new Error('I crashed!');
}
wtedy twój błąd zostanie przechwycony przez granicę błędu i możesz go przetworzyć i wyświetlić wdzięczny komunikat.
Jeśli zmienimy kod w ten sposób:
async componentDidMount()
{
throw new Error('I crashed!');
}
co jest równoważne z tym:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
wtedy twój błąd zostanie po cichu połknięty . Wstydź się, zareaguj ...
Jak więc przetwarzamy błędy? Jedynym sposobem wydaje się być taki wyraźny haczyk:
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
}
}
lub tak:
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
});
}
Jeśli nadal chcemy, aby nasz błąd osiągnął granicę błędu, mogę pomyśleć o następującej sztuczce:
- Złap błąd, spraw, aby program obsługi błędu zmienił stan komponentu
- Jeśli stan wskazuje na błąd, wyrzuć go z
render
metody
Przykład:
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>;
}
}