2020年4月の更新:
この問題は最新のReact 16.13.1で修正されたようです。このサンドボックスの例を参照してください。これを指摘してくれた@abernierに感謝します。
私はいくつかの調査を行い、1つの重要な違いを発見しました
。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>;
}
}