Оновлення квітня 2020 року:
проблема, здається, виправлена в останньому React 16.13.1, дивіться цей приклад пісочниці . Дякуємо @abernier за вказівку на це.
Я провів кілька досліджень, і я виявив одну важливу відмінність:
React не обробляє помилки методів життєвого циклу async.
Отже, якщо ви пишете щось подібне:
componentDidMount()
{
throw new Error('I crashed!');
}
тоді ваша помилка буде зафіксована межею помилки , і ви можете її обробити і відобразити витончене повідомлення.
Якщо ми змінимо такий код:
async componentDidMount()
{
throw new Error('I crashed!');
}
що еквівалентно цьому:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
тоді ваша помилка буде мовчки проковтнута . Сором вам, реагуйте ...
Отже, як ми обробляємо помилки, ніж? Єдиним способом здається, що це явний вилов:
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
або так:
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
Якщо ми все ще хочемо, щоб наша помилка досягла межі помилки, я можу подумати про наступний трюк:
- Ловіть помилку, змушуйте обробник помилок змінити стан компонента
- Якщо стан вказує на помилку, відкиньте її з
render
методу
Приклад:
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>;
}
}