2020年4月更新:
此问题似乎已在最新的React 16.13.1中解决,请参见此沙盒示例。感谢@abernier指出这一点。
我做了一些研究,发现了一个重要的区别:
React不会处理异步生命周期方法中的错误。
因此,如果您编写如下内容:
componentDidMount()
{
throw new Error('I crashed!');
}
那么您的错误将被error boundry捕获,并且您可以对其进行处理并显示优美的消息。
如果我们这样更改代码:
async componentDidMount()
{
throw new Error('I crashed!');
}
这等效于:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
那么您的错误就会被默默地吞噬。对你感到羞耻,React ...
那么,我们如何处理错误呢?唯一的方法似乎是这样的显式捕获:
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>;
}
}