Обновление от апреля 2020 года:
проблема, похоже, исправлена в последней версии React 16.13.1, см. Этот пример песочницы . Спасибо @abernier за указание на это.
Я провел небольшое исследование и обнаружил одно важное отличие:
React не обрабатывает ошибки асинхронных методов жизненного цикла.
Итак, если вы напишете что-то вроде этого:
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>;
}
}