見出し画像

React/Preactのエラー処理の共通化

こんにちは!オプティマインドのウェブエンジニアドリューです。今年のアドベントカレンダーの16日目に初めての技術的な記事を書いてみました!

今回はタイトルの通り、React/Preactのエラー処理の共通化について少し解説しながら一緒にサンプルコードを書きます。

オプティマインドではReactのみを使っているのですが、趣味でPreactを触ったりしていて、ほぼ一緒なのでPreactを使います。

問題定義


ネットワークが切れたり、サーバーが壊れたり、ストレージが壊れたりすることがあるので、事前にエラーを予知して対処することは重要です。

ローカルでのエラーに対処する時、サーバーのエラーと違って自動的にログが残る可能性が低いため、Sentryみたいなサービスを使って残す仕組みを入れる必要がありますし、ユーザーにも丁寧にエラーを表示する必要があります。

解決策


一貫性のある、信頼性の高い、DRYなコードを保つためには、エラー処理の共通化が必要です。

その一つの方法として、エラーをキャッチしてユーザーにメッセージを表示するエラーハンドラー専用コンポーネントを作成することができます。

実装方法


コンポーネント内部からフェッチする、シンプルなアプローチを一例としてあげます。React-QueryやSWRのようなモダンなライブラリを使うこともできますが、複雑になりすぎないようにAxiosを使って偽のリソースを取得することにします。

ここでエラーダイアログのコンポーネントは作成しませんが、設計する際には、1)何が起こったのか、2)なぜエラー起こったのか、3)それに対して何をすべきなのか、を含めてユーザーに知らせる必要があります。

まず、アプリを作成しましょう。私はViteの、Preactビルドツールを使ってアプリを作成しましたが、ReactやPreactのアプリを作成できるツールのどれでも大丈夫です。 

この例では、ViteのPreactビルドツールから生成されたソースをそのまま再利用することにします。そこでは、よくあるクリックされるとカウンタが増加するボタンがあります。その機能にフォーカスしてサーバーと同期する処理を次に追加します。

図1:App Component

次に、API呼び出しを試みるコンポーネント「SyncCount」を作成します。

図2:SyncCount Component

ネットワークリクエストが404ステータスで失敗し、コンソールエラーが発生しますが、それ以外は特に何も起こりません。それでは、エラー処理の作成に取りかかりましょう。

まず、コールバックを格納するコンテキストを作成します。このコンテキストは、任意のコンポーネントで使用することができるようになります。

図3:Error Handler Context

次に、このコンテキストを初日するプロバイダを作成しましょう。

図4:Error Handler Provider

一旦は開発者が確認できる詳細なコンソールログとエラーの存在で表示されるボタンを追加します。そしてこのボタンをクリックしたらエラーが確認されて消えるというようなモックを作っています。

図5:Error Container

ここでは実装していませんが、ボタンの代わりにデータを好きなように表示するカスタムダイアログを実装することも考えられますね。

エラーコンテナコンポーネントができたので、アプリ全体をラップして、先ほど作成したコールバックにアクセスすることを使うことができます。

図6:App Component with Error Container

さらに簡単にするために、どんなコンポーネントでも簡単に使えるようなカスタムフックも作っておきましょう。

図7:Error Handler Custom Hook

うわー、すごい量でしたね!でももう、カスタムフックをインポートするだけでエラーを発行できます!

最後の一歩としてSync Count コンポーネントにインポートしてみましょう。

図8:Sync Count Component with Error Handling

ここで、ボタンをクリックしてみると、コンソールのエラー出力が綺麗に表示され、「Confirm Error」ボタンが表示されます。それをクリックすると、
エラーの状態がリセットされます。

オプティマインドが直面する具体的な課題


クラスコンポーネントも存在するので、フックを使用することが完全に適応できません。したがって、setErrorメソッドにアクセスする別の方法が必要になります。

また、私たちはRedux-Sagaを使っていてContext APIを基本的に使わないので、Contextの代わりにReduxのエラー専用reducerを構築することが必要でしょう。Redux-Sagaの中で起こったエラーがあった時に、Reduxのアクションを使ってreducerを更新してそのステートを見ているErrorContainerコンポーネントを知らせる必要があるでしょう。

そうすると、カスタムフックもいらなくなるのでコンポーネント内から直接アクションを発行するとよさそうですね。

最後に


ここまで読んでいただいてありがとうございます!

オプティマインドでは開発をする上でフロント・バックエンドの縛りはないんですが、個人的には前者の方に関心が強いですね!

そして採用を積極的に行なっているので一緒に働くことが面白いかも!と思っていただけたら是非弊社に一度連絡してみてください。

オプティマインドでは「多様性が進んだ世の中でも、全ての人に物が届く世界を持続可能にする」という物流業界の壮大な社会課題を解決すべく、一緒に働く仲間を大募集中です。少しでも興味が湧いた方はカジュアル面談も大歓迎ですので、気軽にお声がけください!


この記事が気に入ったらサポートをしてみませんか?