要約
- React では v16 から React Hooks の登場で Function Component がスタンダードになっている
- Error Boundary を実装する際はライフサイクルメソッドの
static getDerivedStateFromError()
か componentDidCatch()
のいずれか(または両方)を使わないといけない、つまり Class Component が必須になっている
- react-error-boundarでは Error Boundary を Function Component で扱えるラッパーを提供してくれる
Error Boundary とは
React では Error Boundary という子コンポーネントツリーでエラーが発生した際にクラッシュした UI を表示させる代わりに、フォールバック用の UI を表示するコンポーネントがあります。これはユーザーが壊れた画面で操作することにより、サービスに問題が起こることを防ぐことができます。
このようなエラーハンドリングは try/catch
で行うことが一般的ですが、これは命令型のコード(関数の実行など)でしか動作しません。そのため、コンポーネントのような宣言型でエラーに応じた処理を行うためには別の方法を取らなければなりません。react ではライフサイクルメソッドの static getDerivedStateFromError()
か componentDidCatch()
のいずれか(または両方)を使うことで実装できます。
以下は公式ドキュメントからの抜粋です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
|
1
2
3
4
|
// 使い方
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
|
error boundary とは
これらを関数型でうまく扱える方法がないか探したところ、react-error-boundary
というパッケージがありました。
なので実装例とともに紹介します。
Function Component で Error Boundary を試す
react-error-boundaryというレンダリング時のエラーを扱いやすくするラッパーを提供してくれています。
試しに定期的にエラーを引き起こすコンポーネントを作成します。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import React from "react";
import ReactDOM from "react-dom";
// 定期的にエラーを起こすコンポーネント
const App: React.FC = () => {
const rnd = Math.random();
if (rnd <= 0.7) {
throw new Error("Something went wrong!");
}
return <div>OK</div>;
};
ReactDOM.render(<App />, document.getElementById("root"));
|
現状のままだと <App />
がエラーを出した場合、真っ白な画面(壊れた UI)が表示されてしまいます。
react-error-boundary
を使うことでエラー時のコンポーネントを関数コンポーネントとして別に用意し、エラー時のフォールバック用のコンポーネントとして表示できます。以下が簡単な実装例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
import React from "react";
import ReactDOM from "react-dom";
import { ErrorBoundary, FallbackProps } from "react-error-boundary";
// 定期的にエラーを起こすコンポーネント
const App: React.FC = () => {
const rnd = Math.random();
if (rnd <= 0.7) {
throw new Error("Something went wrong!");
}
return <div>OK</div>;
};
// エラー時のフォールバック用のコンポーネント
const ErrorFallback: React.FC<FallbackProps> = ({ error, resetErrorBoundary }) => {
return (
<div role="alert">
<p>Error Message</p>
<pre>{error!.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
};
ReactDOM.render(
<ErrorBoundary FallbackComponent={ErrorFallback}>
<App />
</ErrorBoundary>,
document.getElementById("root")
);
|
これによりエラーの際に、<ErrorFallback/>
で定義した代わりの UI を表示させることができます。

より詳しく知りたい方は参考資料をご覧ください。
参考資料