Error Boundary
多くのフロントエンド開発者は、エラー処理とログに関する記録を見落としがちです。
コードがエラーをスローした場合、正しい処理をする必要がある。
Reactでのエラーはコンポーネント内で適切な処理をしなければいけません。
コンポーネント内で発生したJavaScriptエラーは Reactの内部まで侵されます。
つまり
エラー境界の外側でエラーが発生すると Reactコンポーネントツリー全体がアンマウントされアプリケーションそのものがクラッシュされます。
React16からは、開発時に『render()』内で発生したエラーはコンポーネントのスタックトレースとして
コンポーネントツリーがどこでエラーが発生してるのかファイル名や行番号まで表示し正確に分かるようになってます。
これはCreate React Appでの開発の際はデフォルトで最初から有効になっております。
Create React Appを使用しない場合
この機能は開発用であり、本番環境では必ず無効化にしなければいけない決まりがあります。
Reactのエラーを管理、ログとして記録する方法があります。
クラスコンポーネントの場合
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { //フォールバックUIが表示されるように状態の更新 return { hasError: true }; } componentDidCatch(error, errorInfo) { //エラーをエラー報告サービスに記録 logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { //フォールバックUIをレンダリング return <h1>Something went wrong.</h1>; } return this.props.children; } }
<ErrorBoundary> <MyComponent /> </ ErrorBoundary>
使用する場合はコンポーネント内にラップしてあげるだけです。
クラスコンポーネントを使用している時は、この『componentDidCatch()』ライフサイクルメソッド機能でエラーログ情報を記録する事ができます。
それだけではなく、静的関数である
getDerivedStateFromError(error)
を使用して状態を更新し『render』メソッド内でエラーが発生した場合にJavaScriptエラーをキャッチし記録してから
フォールバックUIを表示します。
これらはエラー処理をする為の優れた最善の方法となります。
気をつけなければいけない点があります。
componentDidCatch()ライフサイクルメソッドは、『レンダリング中』『ライフサイクルメソッド内』または子コンポーネントのコンストラクター内でエラーが発生した場合にのみ呼び出しが可能となります。
なので『イベントハンドラー』『非同期コールバック』『サーバー側のレンダリング』などでエラー処理は不可能になります。
Try-Catchを使用したエラー処理
Try-Catchブロックに関しては、エラー境界によりキャッチされる事がないエラーを処理する為に使われたりします。
しかし子コンポーネントの例外をキャッチしません プログラムの処理を命令する時のコードのみで動作されます。
なので子コンポーネントの例外を処理する為の最善方法とは言えません。
関数コンポーネントの
Error Boundary
こちらでインストールします。
npm install --save react-error-boundary
GitHub - bvaughn/react-error-boundary: Simple reusable React error boundary component
react-error-boundarではError Boundaryを関数コンポーネントでも使用できるラッパーを提供しています
react-error-boundaryパッケージを使用します。
関数コンポーネントでのError-Boundaryはエラー処理を簡潔にしエラー処理の制限が解放されたものになります。
フォールバックを表示しエラー境界と同じようにログを記録しアプリケーションの状態をリセットし エラーがまた起きないように再発防止をする事が可能になります。
import {ErrorBoundary} from 'react-error-boundary' function MyFallbackComponent({error, resetErrorBoundary}) { return ( <div role="alert"> <p>Something went wrong:</p> <pre>{error.message}</pre> <button onClick={resetErrorBoundary}>Try again</button> </div> ) } export default function App() { return ( <ErrorBoundary FallbackComponent={MyFallbackComponent} onError={(error, errorInfo) => errorService.log({ error, errorInfo })} onReset={() => { // 状態のリセット }} > <MyErrorProneComponent /> </ErrorBoundary> ); }
そしてクラスとの違いとしては、『use』カスタムHookを使用すればイベントハンドラーと非同期のコードエラー処理を可能にします。
アプリケーション内で複数の異なるエラー処理を記述して使用する事もありません。
今回はここまでの紹介にします、いずれしっかりとした内容の記事を書きます!
ほとんどのフロントエンド開発者はコンソールログに関しては精通しておりますよね。
ですがReactでのエラーをログに記録していく方法を理解している開発者の方はごく少数です。
この記事を読み、自分自身の力でエラーの処理を適切に記録し高品質なアプリケーション開発に役立つ事を私は願っています。
そして素敵なコーディングライフを送って下さい。