Concevoir les Error Boundaries avec Claude Code : du frontend à l'API
Découvrez concevoir les Error Boundaries avec Claude Code : du frontend à l'API. Conseils pratiques et exemples de code inclus.
エラーバウンダリとは
エラーバウンダリは、アプリケーションの一部でエラーが発生しても全体がクラッシュしないようにする防御的な設計パターンです。Claude Codeを使えば、フロントエンドとバックエンドの両方で一貫したエラー処理を設計できます。
React Error Boundary
import { Component, ErrorInfo, ReactNode } from "react";
interface ErrorBoundaryProps {
children: ReactNode;
fallback?: ReactNode;
onError?: (error: Error, errorInfo: ErrorInfo) => void;
}
interface ErrorBoundaryState {
hasError: boolean;
error: Error | null;
}
class ErrorBoundary extends Component<
ErrorBoundaryProps,
ErrorBoundaryState
> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error("Error caught by boundary:", error, errorInfo);
this.props.onError?.(error, errorInfo);
// Send to error monitoring service
reportError(error, {
componentStack: errorInfo.componentStack,
});
}
render() {
if (this.state.hasError) {
return (
this.props.fallback || (
<div className="error-fallback">
<h2>エラーが発生しました</h2>
<p>{this.state.error?.message}</p>
<button onClick={() => this.setState({ hasError: false, error: null })}>
再試行
</button>
</div>
)
);
}
return this.props.children;
}
}
関数コンポーネント向けフック
import { useCallback, useState } from "react";
function useErrorHandler() {
const [error, setError] = useState<Error | null>(null);
if (error) {
throw error; // 親のError Boundaryでキャッチ
}
const handleError = useCallback((err: unknown) => {
if (err instanceof Error) {
setError(err);
} else {
setError(new Error(String(err)));
}
}, []);
const withErrorHandling = useCallback(
<T,>(fn: () => Promise<T>) => {
return async () => {
try {
return await fn();
} catch (err) {
handleError(err);
return undefined;
}
};
},
[handleError]
);
return { handleError, withErrorHandling };
}
API エラーレスポンスの標準化
// エラーコード定義
enum ErrorCode {
VALIDATION_ERROR = "VALIDATION_ERROR",
NOT_FOUND = "NOT_FOUND",
UNAUTHORIZED = "UNAUTHORIZED",
FORBIDDEN = "FORBIDDEN",
CONFLICT = "CONFLICT",
INTERNAL_ERROR = "INTERNAL_ERROR",
RATE_LIMITED = "RATE_LIMITED",
}
interface ApiError {
code: ErrorCode;
message: string;
details?: Record<string, unknown>;
requestId: string;
timestamp: string;
}
class AppError extends Error {
constructor(
public code: ErrorCode,
message: string,
public statusCode: number,
public details?: Record<string, unknown>
) {
super(message);
this.name = "AppError";
}
static notFound(resource: string) {
return new AppError(
ErrorCode.NOT_FOUND,
`${resource} not found`,
404
);
}
static validation(details: Record<string, string>) {
return new AppError(
ErrorCode.VALIDATION_ERROR,
"Validation failed",
400,
details
);
}
static unauthorized(message = "Authentication required") {
return new AppError(ErrorCode.UNAUTHORIZED, message, 401);
}
}
グローバルエラーハンドラー
import { v4 as uuidv4 } from "uuid";
function globalErrorHandler(
err: Error,
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
const requestId = uuidv4();
if (err instanceof AppError) {
// 業務エラー
return res.status(err.statusCode).json({
code: err.code,
message: err.message,
details: err.details,
requestId,
timestamp: new Date().toISOString(),
});
}
// 予期しないエラー
console.error(`[${requestId}] Unexpected error:`, err);
res.status(500).json({
code: ErrorCode.INTERNAL_ERROR,
message: "An unexpected error occurred",
requestId,
timestamp: new Date().toISOString(),
});
}
// 登録順序が重要:ルーターの後に配置
app.use(globalErrorHandler);
非同期エラーのキャッチ
// asyncHandler ラッパー
function asyncHandler(
fn: (
req: express.Request,
res: express.Response,
next: express.NextFunction
) => Promise<void>
) {
return (
req: express.Request,
res: express.Response,
next: express.NextFunction
) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
}
// Usage example
router.get(
"/users/:id",
asyncHandler(async (req, res) => {
const user = await prisma.user.findUnique({
where: { id: req.params.id },
});
if (!user) {
throw AppError.notFound("User");
}
res.json({ data: user });
})
);
階層的エラーバウンダリ
React側では複数のError Boundaryを階層的に配置します。エラー処理の設計をClaude Codeに依頼する際の参考にしてください。プロンプトの書き方は効果的なプロンプト5つのTips、コード品質の改善にはリファクタリング自動化も役立ちます。
function App() {
return (
<ErrorBoundary fallback={<FullPageError />}>
<Header />
<ErrorBoundary fallback={<SidebarFallback />}>
<Sidebar />
</ErrorBoundary>
<ErrorBoundary fallback={<ContentFallback />}>
<MainContent />
</ErrorBoundary>
</ErrorBoundary>
);
}
エラーハンドリングの設計原則についてはMDN Web Docs: Error handlingが参考になります。Claude Codeの詳細は公式ドキュメントを確認してください。
Summary
エラーバウンダリはユーザー体験を損なわないための重要な設計パターンです。Claude Codeを使えば、フロントエンドからAPIまで一貫したエラー処理を効率的に実装できます。
Related Posts
Maîtriser les Hooks de Claude Code : Formatage automatique, tests automatiques et plus encore
Apprenez à configurer le formatage et les tests automatiques avec les hooks de Claude Code. Inclut des exemples de configuration pratiques et des cas d'utilisation concrets.
Configuration des serveurs MCP dans Claude Code et cas d'utilisation pratiques
Un guide complet sur les capacités des serveurs MCP de Claude Code. Apprenez à connecter des outils externes, configurer des serveurs et découvrez des exemples d'intégration concrets.
Le guide complet pour rédiger un CLAUDE.md : Bonnes pratiques de configuration de projet
Un guide approfondi pour rédiger des fichiers CLAUDE.md efficaces. Apprenez à communiquer votre stack technologique, vos conventions et la structure de votre projet pour maximiser la qualité des réponses de Claude Code.