Mastering Error Handling for React in 2025: Best Practices and Examples
記事は上記記事を意訳したものです。
※当ブログでの翻訳記事は元サイト様に許可を得て掲載しています。
エラーハンドリングはあらゆるReactアプリケーションの重要な側面であり、問題が発生した場合でもスムーズなユーザー体験を確保します。この記事では、フォーム、サーバーデータフェッチングなど、様々なタイプのコンポーネントでのエラー処理について、2025年に備えて実践的な例を用いて説明します。まず、適切なエラーハンドリングがアプリケーションにもたらす利点を理解しましょう。
- エラーハンドリングが重要な理由
- Reactアプリケーションにおけるエラーの種類
- UIレンダリングエラーに対するエラー境界
- フォームでのエラー処理
- データフェッチングにおけるエラー処理
- 集中型エラー処理
- Reactにおけるエラー処理の一般的なベストプラクティス
エラーハンドリングが重要な理由
適切なエラーハンドリングは以下に役立ちます:
- アプリが壊れることなく、ユーザーに問題を知らせる
- 詳細なエラー情報を取得してアプリケーションのデバッグを行う
- 全体的なユーザー体験を向上させる
Reactアプリケーションにおけるエラーの種類
エラーハンドリングの必要性が分かったところで、様々な種類のエラーを簡単にリストアップし、その後それらの詳細な処理方法について詳しく説明します。
- UIレンダリングエラー: React コンポーネント自体の問題
- ユーザー入力エラー: フォームに無効なデータを入力するなど、ユーザーのミス
- サーバーエラー: サーバーからデータを取得したり送信したりする際の問題
UIレンダリングエラーに対するエラー境界
エラー境界(Error Boundaries)は、子コンポーネントのJavaScriptエラーをキャッチするように設計されたReactコンポーネントです。これにより、単一の欠陥のあるコンポーネントによってアプリ全体がクラッシュするのを防ぎます。
コード例:エラー境界
import React from 'react'; class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { console.error("Error captured:", error, errorInfo); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } export default ErrorBoundary;
使用方法
エラーが発生する可能性のあるコンポーネントをErrorBoundaryでラップします。フェイルセーフとして、アプリケーション全体をエラー境界で囲むことをお勧めします。
<ErrorBoundary> <MyComponent /> </ErrorBoundary>
フォームでのエラー処理
フォームはユーザー入力エラーの一般的な原因です。react-hook-formやFormikなどのライブラリを使用することで、フォームのバリデーションとエラー処理が簡素化できます。
コード例:ログインフォームのバリデーション
import React from 'react'; import { useForm } from 'react-hook-form'; function LoginForm() { const { register, handleSubmit, formState: { errors } } = useForm(); const onSubmit = (data) => { console.log("Form data submitted:", data); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <div> <label>Email:</label> <input {...register("email", { required: "Email is required" })} /> {errors.email && <span>{errors.email.message}</span>} </div> <div> <label>Password:</label> <input type="password" {...register("password", { required: "Password is required" })} /> {errors.password && <span>{errors.password.message}</span>} </div> <button type="submit">Login</button> </form> ); } export default LoginForm;
ベストプラクティス: 常にユーザーが入力を修正するための明確なエラーメッセージを提供しましょう。
データフェッチングにおけるエラー処理
サーバーからデータを取得する際には、ネットワーク問題や無効な応答などのエラーが発生する可能性があります。axiosやReactのfetchなどのライブラリを使うと、これらのエラーを効果的に処理できます。
コード例:エラー処理を含むデータフェッチング
import React, { useEffect, useState } from 'react'; function DataFetcher() { const [data, setData] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchData() { try { const response = await fetch('https://api.example.com/data'); if (!response.ok) { throw new Error('Failed to fetch data'); } const result = await response.json(); setData(result); } catch (err) { setError(err.message); } finally { setLoading(false); } } fetchData(); }, []); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return <div>Data: {JSON.stringify(data)}</div>; } export default DataFetcher;
ベストプラクティス: ローディング状態を使用してデータが取得中であることを示し、フォールバックUIやメッセージを表示してサーバーエラーを適切に処理しましょう。
集中型エラー処理
大規模なアプリケーションでは、React Queryやグローバルエラー境界を使用してエラー処理を一元化することを検討してください。
例:React Queryの使用
import { useQuery } from 'react-query'; function Products() { const { data, error, isLoading } = useQuery('products', fetchProducts); if (isLoading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <ul> {data.map(product => ( <li key={product.id}>{product.name}</li> ))} </ul> ); } async function fetchProducts() { const response = await fetch('https://api.example.com/products'); if (!response.ok) { throw new Error('Failed to fetch products'); } return response.json(); }
ベストプラクティス: 一元化されたエラー処理は一貫性を確保し、デバッグを簡素化します。
Reactにおけるエラー処理の一般的なベストプラクティス
エラー処理を実装する際に注意すべき点として、すべてのベストプラクティスをまとめましょう。
- 優雅に失敗する: より良いユーザー体験のために、常にフォールバックUIやエラーメッセージを提供する
- ユーザーに負担をかけない: 簡潔なエラーメッセージを表示し、技術的な専門用語を避ける
- エラーをログに記録する: Sentryなどのログツールを使用して、本番環境でエラーを追跡しデバッグする
- すべての種類のエラーを処理する: サーバーエラー、バリデーションの問題、レンダリングエラーを適切に対処する
- エラーシナリオをテストする: 開発中に様々なエラーケースをシミュレートして堅牢性を確保する
Reactでの効果的なエラー処理は、技術的な正確さとユーザー体験のバランスを取ることです。エラー境界を実装し、ユーザー入力を検証し、サーバーエラーを処理し、ベストプラクティスに従うことで、耐障害性があり、ユーザーフレンドリーなアプリケーションを構築できます。
ここで提供された例は、2025年に向けて取り組んでいるReactプロジェクトに堅牢なエラー処理を組み込むための確かな基礎となるでしょう。