2020 年 4 月更新:
该问题似乎已在最新的 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!'));
}
那么你的错误将被默默地吞噬。为你感到羞耻,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>;
}
}